html,
        body,
        div,
        span,
        applet,
        object,
        iframe,
        h1,
        h2,
        h3,
        h4,
        h5,
        h6,
        p,
        blockquote,
        pre,
        a,
        abbr,
        acronym,
        address,
        big,
        cite,
        code,
        del,
        dfn,
        em,
        img,
        ins,
        kbd,
        q,
        s,
        samp,
        small,
        strike,
        strong,
        sub,
        sup,
        tt,
        var,
        b,
        u,
        i,
        center,
        dl,
        dt,
        dd,
        ol,
        ul,
        li,
        fieldset,
        form,
        label,
        legend,
        table,
        caption,
        tbody,
        tfoot,
        thead,
        tr,
        th,
        td,
        article,
        aside,
        canvas,
        details,
        embed,
        figure,
        figcaption,
        footer,
        header,
        hgroup,
        menu,
        nav,
        output,
        ruby,
        section,
        summary,
        time,
        mark,
        audio,
        video {
            margin: 0;
            padding: 0;
            border: 0;
            font: inherit;
            font-size: 100%;
            vertical-align: baseline;
        }
        html {
            line-height: 1;
        }
        ol,
        ul {
            list-style: none;
        }
        table {
            border-collapse: collapse;
            border-spacing: 0;
        }
        caption,
        th,
        td {
            text-align: left;
            font-weight: normal;
            vertical-align: middle;
        }
        q,
        blockquote {
            quotes: none;
        }
        q:before,
        q:after,
        blockquote:before,
        blockquote:after {
            content: "";
            content: none;
        }
        a img {
            border: none;
        }
        article,
        aside,
        details,
        figcaption,
        figure,
        footer,
        header,
        hgroup,
        main,
        menu,
        nav,
        section,
        summary {
            display: block;
        }
        * {
            box-sizing: border-box;
        }
        html {
            position: relative;
            height: 100%;
            font-size: 16px;
            font-family: 'Lato', sans-serif;
        }
    
    
        body {
            height: 100%;
            width: 100%;
            margin: 0;
            padding-top: 53px;
            padding-bottom: 64px;
        }
    
    
        .header {
            position: fixed;
            top: 0;
            left: 0;
            height: 53px;
            width: 100%;
        }
    
    
        .main {
            height: 100%;
        }
    
    
        .footer {
            position: absolute;
            left: 0;
            bottom: 0;
            height: 64px;
            width: 100%;
        }
    
    
        .team-menu {
            position: relative;
            width: 220px;
            height: 53px;
            line-height: 53px;
            font-weight: 200;
            font-size:2em;
            padding: 0 1rem;
            color: #4341c9;
            background: #01003e;
            border-bottom: 2px solid #372c36;
            text-shadow: -1px 1px 1px black,0px 0px 30px #9b96ff;
            float: left;
            cursor: pointer;
        }
    
    
        .channel-menu_name {
            display: inline-block;
            padding: 0 .5rem 0 1.5rem;
            color: #555459;
            font-size: 1.4rem;
            font-weight: 900;
            line-height: 53px;
            cursor: pointer;
        }
    
    
        .channel-menu_prefix {
            color: #9e9ea6;
            padding-right: .1rem;
            font-weight: 500;
        }
    
    
        .listings {
            height: 100%;
            width: 220px;
            float: left;
            color: #ab9ba9;
            background-color: #555092;
            overflow-y: auto;
            overflow-x: hidden;
        }
    
    
        .message-history {
            margin-left: 220px;
            overflow-y: auto;
            overflow-x: hidden;
            height: 100%;
            padding: 0 18px 1rem 1.5rem;
        }
    
    
        .listings_channels {
            margin: 1rem 0 2rem;
        }
    
    
        .listings_header {
            text-align: left;
            font-size: .8rem;
            line-height: 1.25rem;
            margin: 0 1rem .1rem;
            text-transform: uppercase;
            font-weight: 700;
            color: #ab9ba9;
            width: 165px;
            position: relative;
        }
    
    
        .channel_list {
            list-style-type: none;
            text-align: left;
            color: #ab9ba9;
        }
    
    
        .channel {
            height: 24px;
            line-height: 24px;
            -moz-border-radius-topright: 0.25rem;
            -webkit-border-top-right-radius: 0.25rem;
            border-top-right-radius: 0.25rem;
            -moz-border-radius-bottomright: 0.25rem;
            -webkit-border-bottom-right-radius: 0.25rem;
            border-bottom-right-radius: 0.25rem;
            margin-right: 17px;
            color: #ffffff;
            padding-left: 1rem;
        }
    
    
        .unread {
            color: #ffffff;
            background: #eb4d5c;
            border-radius: 9px;
            padding: 2px 9px;
            font-size: .8rem;
            line-height: 14px;
            font-weight: 700;
            vertical-align: baseline;
            white-space: nowrap;
            text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
            float: right;
            margin-right: 3px;
            margin-top: 3px;
        }
    
    
        .channel.active {
            background: #4c9689;
        }
    
    
        .channel_prefix {
            color: #b2d5c9;
        }
    
    
        .disclaimer {
            font-size: 0.8rem;
            padding-left: 1rem;
            margin-right: 17px;
        }
    
    
        .message {
            position: relative;
            margin-top: .5rem;
            padding: .25rem 2rem .3rem 3rem;
            min-height: 36px;
        }
    
    
        .message_profile-pic {
            position: absolute;
            left: 0;
            display: block;
            -moz-border-radius: 0.2rem;
            -webkit-border-radius: 0.2rem;
            border-radius: 0.2rem;
            width: 36px;
            height: 36px;
            background-image: url("http://i.imgur.com/LikUNLc.png");
            background-size: cover;
        }
    
    
        .message_username {
            font-weight: 900;
            padding-right: .25rem;
            font-size: 0.8em;
            color: #3d3c40 !important;
            margin-left: 0;
            font-style: normal;
            text-decoration: none;
        }
    
    
        .message_timestamp {
            text-align: left;
            display: inline;
            position: relative;
            top: 0;
            left: 0;
            color: #babbbf;
            font-size: 12px;
            line-height: 1.2rem;
            width: 36px;
            margin-right: 0;
            margin-left: 0;
        }
    
    
        .message_content {
            color: #8b898f;
            display: block;
            min-height: 1rem;
        }
    
    
        .user-menu {
            float: left;
            width: 220px;
            height: 100%;
            cursor: pointer;
            background: #01003e;
            border-top: 2px solid #372c36;
            padding: 7px 0 9px 8px;
            height: 4rem;
            position: fixed;
            bottom: 0;
            left: 0;
        }
    
    
        .user-menu_profile-pic {
        }
    
    
        .qrowdfundsmall {
          display: inline-block;
          -moz-border-radius: 0.2rem;
          -webkit-border-radius: 0.2rem;
          border-radius: 0.2rem;
          width: 33px!important;
          height: 33px!important;
        	background-image: url('/qrowdfund/qrowdfundSmall.png');
          background-size: cover;
          vertical-align: text-top;
    
        }
    
        .selected-address {
          color:white;
          font-size:0.6em;
          cursor:copy;
        }
    
        .user-menu_username {
            display: block;
            color: #ffffff;
            font-weight: 900;
            line-height: 1.5rem;
            margin-top: .2rem;
            max-width: 120px;
        }
    
    
        .connection_icon {
            width: 12px;
            height: 12px;
        }
    
    
        .connection_status {
            color: #ab9ba9;
        }
    
    
        .input-box {
            height: 100%;
            margin-left: 220px;
        }
    
    
        .input-box_text {
            font-size: .95rem;
            width: 90%;
            margin-left: 2%;
            margin-bottom: auto;
            line-height: 1.2rem;
            border: 2px solid #e0e0e0;
            -moz-border-radius: 0.2rem;
            -webkit-border-radius: 0.2rem;
            border-radius: 0.2rem;
            -moz-background-clip: padding-box;
            -webkit-background-clip: padding-box;
            background-clip: padding-box;
            color: #3d3c40;
            -webkit-appearance: none;
            -webkit-box-shadow: none;
            -moz-box-shadow: none;
            box-shadow: none;
            outline: 0;
            bottom: 0;
            min-height: 41px !important;
            padding: 9px 5px 9px 8px;
        }
    
        .user-settings legend {
            padding-bottom: 10px;
        }
    
        .user-settings div {
            padding-bottom: 10px;
        }
    
        .channel_name {
            text-decoration: none;
            color: inherit;
        }
    
        .channel {
            cursor: pointer;
            margin-right: 0px;
            padding-right: 0px;
        }
    
        .channel:hover {
            background-color: #2c255d;
        }
    
        #result {
            padding-right: 60px;
            line-height: 40px;
            background-color: aliceblue;
            position: fixed;
            right:0;
            top:5px;
            padding-left:20px;
            font-weight:bold;
            z-index: 10000;
        }
    
        .alert-error {
            background-color: red;
        }
    
        #selected-name option{
          color:black;
        }
    // Generated by CoffeeScript 1.8.0
    (function() {
      var ALPHABET, ALPHABET_MAP, Base58, i;
    
      Base58 = (typeof module !== "undefined" && module !== null ? module.exports : void 0) || (window.Base58 = {});
    
      ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
    
      ALPHABET_MAP = {};
    
      i = 0;
    
      while (i < ALPHABET.length) {
        ALPHABET_MAP[ALPHABET.charAt(i)] = i;
        i++;
      }
    
      Base58.encode = function(buffer) {
    	buffer = new Uint8Array(buffer);
        var carry, digits, j;
        if (buffer.length === 0) {
          return "";
        }
        i = void 0;
        j = void 0;
        digits = [0];
        i = 0;
        while (i < buffer.length) {
          j = 0;
          while (j < digits.length) {
            digits[j] <<= 8;
            j++;
          }
          digits[0] += buffer[i];
          carry = 0;
          j = 0;
          while (j < digits.length) {
            digits[j] += carry;
            carry = (digits[j] / 58) | 0;
            digits[j] %= 58;
            ++j;
          }
          while (carry) {
            digits.push(carry % 58);
            carry = (carry / 58) | 0;
          }
          i++;
        }
        i = 0;
        while (buffer[i] === 0 && i < buffer.length - 1) {
          digits.push(0);
          i++;
        }
        return digits.reverse().map(function(digit) {
          return ALPHABET[digit];
        }).join("");
      };
    
      Base58.decode = function(string) {
        var bytes, c, carry, j;
        if (string.length === 0) {
          return new (typeof Uint8Array !== "undefined" && Uint8Array !== null ? Uint8Array : Buffer)(0);
        }
        i = void 0;
        j = void 0;
        bytes = [0];
        i = 0;
        while (i < string.length) {
          c = string[i];
          if (!(c in ALPHABET_MAP)) {
            throw "Base58.decode received unacceptable input. Character '" + c + "' is not in the Base58 alphabet.";
          }
          j = 0;
          while (j < bytes.length) {
            bytes[j] *= 58;
            j++;
          }
          bytes[0] += ALPHABET_MAP[c];
          carry = 0;
          j = 0;
          while (j < bytes.length) {
            bytes[j] += carry;
            carry = bytes[j] >> 8;
            bytes[j] &= 0xff;
            ++j;
          }
          while (carry) {
            bytes.push(carry & 0xff);
            carry >>= 8;
          }
          i++;
        }
        i = 0;
        while (string[i] === "1" && i < string.length - 1) {
          bytes.push(0);
          i++;
        }
        return new (typeof Uint8Array !== "undefined" && Uint8Array !== null ? Uint8Array : Buffer)(bytes.reverse());
      };
    
    }).call(this);
    $("#login").show();
    
        $("#btn-save-settings").click(function(e) {
            e.preventDefault();
    
            updateValue();
        })
    
        $("#btn-login").click(function(e) {
            e.preventDefault();
            pass = $("#password").val();
            $("#login").hide();
    
            doBrain(pass)
        })
    
    
    
    
        var updateValue;
        updateValue = function() {
    
            document.getElementById('result').innerHTML = '<div class=\"alert alert-info\" role=\"alert\">Saving...please confirm the security call and then wait until you get a success message! If the transaction amount is high this may take some time...<br></div>';
    
            image = document.getElementById('icon-data').value
            username = document.getElementById('settings-username').value
            address = $('#settings-name option:selected').val();
            var iconStr = "qrack-icon"
            var userStr = "qrack-username"
    
    
            jsonstring = {
                "addcomplete": "{\"" + iconStr + "\":\"" + image + "\",\"" + userStr + "\":\"" + username + "\"}"
            }
    
    
            $.post(
                    nodeUrl + "/index/api.html", {
                        type: 'post',
                        apiurl: '/namestorage/update/' + address,
                        json: JSON.stringify(jsonstring)
                    })
                .done(function(data) {
                    if (data.type == 'success') {
                        document.getElementById('result').innerHTML = "<div class=\"alert alert-success\" role=\"alert\">Key successfully saved.<br></div>";
                    } else if (data.type == 'parametersMissing') {
                        document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">Some parameters are missing.<br></div>";
                    } else if (data.type == 'badKey') {
                        document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">This key is an internal qora key and can't be edited this way!<br></div>";
                    } else if (data.type == 'error') {
                        try {
                            var error = JSON.parse(data.error);
                            message = error.message;
                        } catch (e) {
                            message = data.error;
                        }
    
                        document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">An error occurred while saving the website.<br>" + message + "<br></div>";
                    } else {
                        document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">Unknown response:<br>" + data + "<br></div>";
                    }
                })
                .fail(function(xhr, textStatus, errorThrown) {
                    try {
                        var error = JSON.parse(xhr.responseText);
                        message = error.message;
                    } catch (e) {
                        message = xhr.responseText;
                    }
    
                    document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">An error occurred while saving the website.<br>" + message + "<br></div>";
                });
        };
    
        function processCommand() {
          command = $(".input-box_text").val();
          commandParts = command.split(" ");
          if (commandParts[0].toLowerCase() == "/post") {
            commandParts[0] = "post"
          } else if (commandParts[0].toLowerCase() == "/get") {
            commandParts[0] = "get"
          } else if  (commandParts[0].toLowerCase() == "/send") {
            if (commandParts.length != 3) {
              return false;
            }
            doPaymentTransaction(commandParts[1], commandParts[2]);
            return;
          } else if  (commandParts[0].toLowerCase() == "/registername") {
            if (commandParts.length != 2) {
              return false;
            }
            doRegisterName(commandParts[1], '{"defaultkey":""}');
            return;
          } 
          else {
            document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">Should be either 'post' or 'get'<br></div>";
            return false;
          }
          $.post(
                  nodeUrl + "/index/api.html", {
                      type: commandParts[0],
                      apiurl: commandParts[1],
                      json: (commandParts[2])?commandParts[2]:""
                  })
              .done(function(data) {
                  if (data.type == 'success') {
                    var results = JSON.parse(data.result)
    
                            htmlT = '<div class="message">' +
                                '<a href="" class="message_profile-pic"></a>' +
                                '<a href="" class="message_username">System Response</a>' +
                                '<span class="message_timestamp">' + new Date() + '</span>' +
                                '<span class="message_star"></span>' +
                                '<span class="message_content">' + JSON.stringify(results,null,"\t") + '</span>' +
                                '</div>'
    
                            $(".message-history .active").append(htmlT);
    
                            var objDiv = document.getElementById("message-scroll");
                            objDiv.scrollTop = objDiv.scrollHeight + 100;
    
                      document.getElementById('result').innerHTML = "<div class=\"alert alert-success\" role=\"alert\">Request successfully sent.<br></div>";
                  } else if (data.type == 'parametersMissing') {
                      document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">Some parameters are missing.<br></div>";
                  } else if (data.type == 'badKey') {
                      document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">This key is an internal qora key and can't be edited this way!<br></div>";
                  } else if (data.type == 'error') {
                      try {
                          var error = JSON.parse(data.error);
                          message = error.message;
                      } catch (e) {
                          message = data.error;
                      }
    
                      document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">An error occurred while saving the website.<br>" + message + "<br></div>";
                  } else {
                      document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">Unknown response:<br>" + data + "<br></div>";
                  }
              })
              .fail(function(xhr, textStatus, errorThrown) {
                  try {
                      var error = JSON.parse(xhr.responseText);
                      message = error.message;
                  } catch (e) {
                      message = xhr.responseText;
                  }
    
                  document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">An error occurred while saving the website.<br>" + message + "<br></div>";
              });
        }
    
        $("#btn-send").click(function(e) {
            e.preventDefault();
            if ($(".input-box_text").val().startsWith("/")) {
                processCommand();
            } else {
              rawTx = doMessageTransaction();
            }
            $(".input-box_text").val("");
            return false;
        });
    
        var channels = {
            "QaWkWmYSvdsi8WBqwN2ScdXQfSBb5sm6Zk": "General",
            "QaxiR439Q9nwwqg4WX9i5N88wfwFoKKJBb": "Technical",
            "Qai3un9xKMbhUEAjhUj2X3aC9wFq6XVvcM": "Trolling"
        };
    
        $('.user-settings-btn').click(function(e) {
    
            e.preventDefault();
            $(".message-history").toggle();
            $(".user-settings").toggle();
            return false;
        });
        first = true;
        Array.prototype.filter.call(Object.keys(channels), function(item) {
            channelStr = '<li class="channel" id="' + item + '">' +
                '<span class="channel_name">' +
                '	<span class="unread">' +
                '		0' +
                '	</span>' +
                '	<span>' +
                '		<span class="prefix">#</span>' +
                '<span class="channel-name">' + channels[item] + '</span>' +
                '</span>' +
                '</span>' +
                '</li>';
            $(".channel_list").append(channelStr)
            if (first) {
                $(".message-history").append('<div id="' + item + '-messages" class="active"></div>');
                first = false;
            } else {
                $(".message-history").append('<div style="display:none" id="' + item + '-messages"></div>');
    
            }
    
            getTxs(item, 2000);
    
        });
    
        function txComparator(a, b) {
          return (a.blockHeight == b.blockHeight) ? a.timestamp * 1 - b.timestamp * 1 : a.blockHeight * 1 - b.blockHeight * 1;
    
        }
    
        function getTxs(item, limit) {
    
            $.post(
                    nodeUrl + "/index/api.html", {
                        type: 'get',
                        apiurl: 'transactions/address/' + item + '/type/17/limit/' + limit
                    })
                .done(function(data) {
                    if (data.type == "success") {
                        parseData(data.result, item)
                    } else if (data.type == 'apicallerror') {
                        parseData(data.errordetail, item)
                    } else if (data.type == 'error') {
                        try {
                            var error = JSON.parse(data.error);
                            message = error.message;
                        } catch (e) {
                            message = data.error;
                        }
    
                        document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">An error occurred while fetching chat history.<br>" + message + "<br></div>";
                    } else {
                        document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">Unknown response:<br>" + data.type + "<br></div>";
                    }
                })
                .fail(function(xhr, textStatus, errorThrown) {
                    document.getElementById('result').innerHTML = '<div class=\"alert alert-danger\" role=\"alert\">ERROR<br>' + xhr.responseText + '<br></div>';
                });
        }
    
        function parseData(data, item) {
        var results = JSON.parse(data)
        results = results.sort(txComparator);
        Array.prototype.filter.call(results, function(message) {
    
            if (document.getElementById(message.signature) === null) {
    
                htmlT = '<div class="message" id=' + message.signature + '>' +
                    '<a href="" class="message_profile-pic"></a>' +
                    '<a href="" class="message_username">' + message.creator + '</a>' +
                    '<span class="message_timestamp">' + new Date(message.timestamp * 1) + '</span>' +
                    '<span class="message_star"></span>' +
                    '<span class="message_content">' + $( $.parseHTML(message.data) ).text() + '</span>' +
                    '</div>'
    
                $("#" + item + "-messages").append(htmlT);
    
                var objDiv = document.getElementById("message-scroll");
                objDiv.scrollTop = objDiv.scrollHeight + 100;
            } else {
                htmlT = '<a href="" class="message_profile-pic"></a>' +
                    '<a href="" class="message_username">' + message.creator + '</a>' +
                    '<span class="message_timestamp">' + new Date(message.timestamp * 1) + '</span>' +
                    '<span class="message_star"></span>' +
                    '<span class="message_content">' + $( $.parseHTML(message.data) ).text() + '</span>'
                $("#" + message.signature).html(htmlT);
    
            }
        });
        }
    
        function syncChat() {
            Array.prototype.filter.call(Object.keys(channels), function(item) {
                getTxs(item, 200);
            });
        }
    
        lastBlock = 0;
        //check unconfirmed
        setInterval(function() {
            Array.prototype.filter.call(Object.keys(channels), function(item) {
                $.post(
                        nodeUrl + "/index/api.html", {
                            type: 'get',
                            apiurl: '/transactions/network'
                        })
                    .done(function(data) {
                        if (data.type == "success") {
                            var results = JSON.parse(data.result)
                            results = results.sort(txComparator);
                            Array.prototype.filter.call(results, function(message) {
                                if (message.recipient == item && message.type == 17 && document.getElementById(message.signature) === null) {
                                    htmlT = '<div class="message" id=' + message.signature + '>' +
                                        '<a href="" class="message_profile-pic"></a>' +
                                        '<a href="" class="message_username">' + message.creator + '</a>' +
                                        '<span class="message_timestamp">' + new Date(message.timestamp * 1) + ' (unconfirmed)</span>' +
                                        '<span class="message_star"></span>' +
                                        '<span class="message_content">' + $( $.parseHTML(message.data) ).text() + '</span>' +
                                        '</div>'
                                    $("#" + item + "-messages").append(htmlT);
    
                                    var objDiv = document.getElementById("message-scroll");
                                    objDiv.scrollTop = objDiv.scrollHeight + 100;
    
                                }
                            });
                        }
                    })
                    .fail(function(xhr, textStatus, errorThrown) {
                        document.getElementById('result').innerHTML = '<div class=\"alert alert-danger\" role=\"alert\">ERROR<br>' + xhr.responseText + '<br></div>';
                    });
    
                $.post(
                        nodeUrl + "/index/api.html", {
                            type: 'get',
                            apiurl: 'blocks/height'
                        })
                    .done(function(data) {
                        if (data.type == "success") {
                            var blockHeight = JSON.parse(data.result)
                            if (lastBlock != blockHeight) {
                                syncChat();
                                lastBlock = blockHeight;
                            }
                            $('.channel-menu_prefix').html('#' + blockHeight + ' blocks');
    
                        }
                    })
                    .fail(function(xhr, textStatus, errorThrown) {
                        document.getElementById('result').innerHTML = '<div class=\"alert alert-danger\" role=\"alert\">ERROR<br>' + xhr.responseText + '<br></div>';
                    });
            });
            setTimeout(function() {
                $('.alert').remove();
            }, 5000);
        }, 3000);
    
        $(".channel").click(function(e) {
            e.preventDefault();
            $(".message-history .active").removeClass('active').toggle();
            $("#" + $(this).attr('id') + "-messages").addClass('active').toggle();
        });
    
        $(".input-box_text").keyup(function(event) {
            if (event.keyCode == 13) {
                $("#btn-send").click();
            }
        });
    
        $('#selected-name').on('change', function (e) {
        var optionSelected = $("option:selected", this);
        var valueSelected = this.value;
        $('.selected-address').html(optionSelected.html());
    
    });
    
        $('#form').ajaxForm({
            beforeSubmit: function() {
                $('#results').html('Submitting...');
            },
            success: function(data) {
    
                if (data.type == 'success') {
                    document.getElementById('profile-icon').src = data.result + "";
                    $("#icon-data").val(data.result)
                    document.getElementById('result').innerHTML = "<div class=\"alert alert-success\" role=\"alert\">" + "The file has been added to the key! You still need to submit the result to make it persistent!" + "<br></div>";
                } else if (data.type == 'error') {
                    document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">" + data.result + "<br></div>";
                } else {
                    document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">" + "Unknown response" + ":<br>" + data + "<br></div>";
                }
    
            },
            error: function() {
                document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">" + "An error occured" + ":<br></div>";
            }
        });
    
    <!DOCTYPE html>
    
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title></title>
        <link href='http://fonts.googleapis.com/css?family=Lato:400,700,900' rel='stylesheet' type='text/css'>
    </head>
    
    <style type="text/css">
      {{namestoragemap.getOpt("quothprototype","quoth.css")}}
    </style>
    
    <div id="login" style="
        display:none;
        width: 100%;
        height: 100vh;
        background-color: hsla(228,90%,4%,0.8);
        position: fixed;
        top: 0;
        z-index: 10000;
        line-height: 50vh;
        text-align: center;
        margin-left: auto;
        margin-right: auto;
    ">
      <legend>Password</legend>
      <div class="col-lg-10">
          <input type="password" placeholder="password" id="password" style="max-width: 80%;vertical-align:top;height: 40px;padding: 2px;min-width: 80%;font-size: 1.2em;">
          <button type="save" id="btn-login" style="vertical-align:top;line-height:34px;" class="btn btn-default">Save</button>
      </div>
    </div>
    
    <div class="main">
        <div class="header">
            <div class="team-menu"><span class="qrowdfundsmall" style="width:20px;height:20px;"></span>uoth</div>
            <div class="channel-menu">
                <span class="channel-menu_name">
    				<span class="channel-menu_prefix">#</span>
    
                </span>
            </div>
        </div>
        <div class="listings">
            <div class="listings_channels">
                <h2 class="listings_header">Channels</h2>
                <ul class="channel_list">
                </ul>
    
            </div>
            <div class="listings_direct-messages"></div>
        </div>
        <div id=result></div>
    
        <div class="message-history" id="message-scroll">
    
    
        </div>
    </div>
    
    <div class="footer">
        <div class="user-menu">
            <span class="user-menu_profile-pic"></span>
            <select class="form-control" id="selected-name" style="max-width:150px">
    
    				</select>
            <span class="selected-address"></span>
            <!--<span class="user-settings-btn" style="color:lightgray;">Settings</span>-->
        </div>
        <div class="input-box">
            <input type="text"  list="mylist" class="input-box_text awesomplete">
            <button class="button" id="btn-send">Send</button>
        </div>
    </div>
    <datalist id="mylist">
    	<option>/get blocks/last</option>
    	<option>/get blocks/height</option>
    	<option>/get qora/status</option>
      <option>/get qora/version</option>
      <option>/get peers</option>
      <option>/get peers/detail</option>
    	<option>/send [address] [amount]</option>
      <option>/registername [name]</option>
    
    </datalist>
    
    <script src="/index/libs/jquery/jquery.2.js"></script>
    <script src="/quothprototype/nacl-fast.js" charset="utf-8"></script>
    <script src="/quothprototype/Base58.js" charset="utf-8"></script>
    <script src="/quothprototype/sha256.js" charset="utf-8"></script>
    <script src="/quothprototype/ripemd160.js" charset="utf-8"></script>
    <script src="/quothprototype/qora.js" charset="utf-8"></script>
    <script src="/quothprototype/common.js" charset="utf-8"></script>
    <script src="/quothprototype/brainwallet.js"></script>
    <script src="/quothprototype/payment.js"></script>
    <script src="/quothprototype/messaging.js"></script>
    <script src="/quothprototype/registername.js"></script>
    <script src="/index/libs/third-party/jquery.form.min.js"></script>
    <link rel="stylesheet" href="/quothprototype/awesomplete.css" />
    <script src="/quothprototype/awesomplete.js" async></script>
    <script src="/quothprototype/quoth.js"></script>
    	var nodeUrl = '';
    
    
    
    
    	function doLoadBalance(base58SenderAccountAddress, elementAccountbalance)
    	{
    		if(base58SenderAccountAddress == '') {
    			elementAccountbalance.val('');
    			return;
    		}
    
    		var nodeUrl = $("#nodeUrl").val();
    
    		$.post( nodeUrl + "/index/api.html", { type: "get", apiurl: "/addresses/balance/" + base58SenderAccountAddress } )
    			.done(function( data ) {
    
    				if(data.type == 'success'){
    					var balanceOfAccount = data.result;
    					elementAccountbalance.val(addCommas(balanceOfAccount));
    				}
    
    				if(data.type == 'apicallerror'){
    					$("#output").val(parseError(data.errordetail));
    					elementAccountbalance.val('');
    				}
    
    			})
    			.fail(function() {
    				$("#output").val( "error" );
    			});
    	}
    
    	function doLoadInfoForName(name, elementNameInfo)
    	{
    		if(name == '') {
    			elementNameInfo.val('');
    			return;
    		}
    
    		if( name.toLowerCase() != name ) {
    			elementNameInfo.val('You must use lowercase letters.');
    			return;
    		}
    
    		var nodeUrl = $("#nodeUrl").val();
    
    		$.post( nodeUrl + "/index/api.html", { type: "get", apiurl: "/names/" + encodeURIComponent(name) } )
    			.done(function( data ) {
    
    				if(data.type == 'success'){
    					var info = JSON.parse(data.result);
    					elementNameInfo.val("Registered by " + info.owner);
    				}
    
    				if(data.type == 'apicallerror'){
    					if(parseError(data.errordetail) == 'name does not exist') {
    						elementNameInfo.val('Name is free. You can register it.');
    					} else {
    						elementNameInfo.val(parseError(data.errordetail));
    					}
    				}
    
    			})
    			.fail(function() {
    				$("#output").val( "error" );
    			});
    	}
    
    	function doNowTime()
    	{
    		var date = new Date();
    		$('#datetime').val(date.toLocaleDateString() + ' ' + date.toLocaleTimeString());
    		$('#timestamp').val(date.getTime());
    	}
    
    	function sleep(ms) {
    		ms += new Date().getTime();
    		while (new Date() < ms){}
    	}
    
    	function addCommas(str)
    	{
    		strbuf = str.toString();
    		if( strbuf.indexOf('.') == -1)
    		{
    			return strbuf.replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1,');
    		}
    		return strbuf.replace(/(\d)(?=(\d\d\d)+([^\d]))/g, '$1,');
    	}
    
    	function removeAllexceptDotAndNumbers (str)
    	{
    		return str.replace(/[^.0-9]/g,"");
    	}
    
    	function removeAllexceptNumbers(str)
    	{
    		return str.replace(/[^0-9]/g,"");
    	}
    
    	function getTextCursorPosition(ele) {
    		return ele.prop("selectionStart");
    	}
    
    	function setTextCursorPosition(ele, pos) {
    		ele.prop("selectionStart", pos);
    		ele.prop("selectionEnd", pos);
    	}
    
    	function parseError(error)
    	{
    		try {
    			var error = JSON.parse(error);
    			message = error.message;
    		} catch (e) {
    			message = error;
    		}
    		return message;
    	}
    
    	function doProcess(txRaw)
    	{
    		if(!txRaw) {
    			return;
    		}
    
    		$.ajax({
    		    type: 'post',
    		    headers: {
    		        "X-FORWARDED-FOR": '127.0.0.1',   //If your header name has spaces or any other char not appropriate
    		    },
    		    dataType: 'json',
    		    url: nodeUrl + "/index/api.html",
    		    data :{
    		      type: 'post',
    		      apiurl: '/transactions/process',
    		      json: txRaw
    		    },
    		    success: function(data) {
    					if(data.type == 'apicallerror')	{
    						document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">"+data.errordetail+"<br></div>";
    
    					}
    					if(data.type == 'success')	{
    						document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">"+data.result+"<br></div>";
    
    						if(isNaN(data.result)){
    							document.getElementById('result').innerHTML = "<div class=\"alert alert-danger\" role=\"alert\">"+data.result+"<br></div>";
    						} else {
    							switch (data.result) {
    								case "1":
    									$("#output").val('VALIDATE_OK');
    									break
    								case "2":
    									$("#output").val('INVALID_ADDRESS');
    									break
    								case "3":
    									$("#output").val('NEGATIVE_AMOUNT');
    									break
    								case "4":
    									$("#output").val('NEGATIVE_FEE');
    									break
    								case "5":
    									$("#output").val('NO_BALANCE');
    									break
    								case "6":
    									$("#output").val('INVALID_REFERENCE');
    									break
    								case "7":
    									$("#output").val('INVALID_NAME_LENGTH');
    									break
    								case "8":
    									$("#output").val('INVALID_VALUE_LENGTH');
    									break
    								case "9":
    									$("#output").val('NAME_ALREADY_REGISTRED');
    									break
    								case "15":
    									$("#output").val('INVALID_AMOUNT');
    									break
    								case "17":
    									$("#output").val('NAME_NOT_LOWER_CASE');
    									break
    								case "27":
    									$("#output").val('INVALID_DATA_LENGTH');
    									break
    								case "34":
    									$("#output").val('INVALID_PAYMENTS_LENGTH');
    									break
    								case "40":
    									$("#output").val('FEE_LESS_REQUIRED');
    									break
    								case "41":
    									$("#output").val('INVALID_RAW_DATA');
    									break
    								case "1000":
    									$("#output").val('NOT_YET_RELEASED');
    									break
    							}
    						}
    					}
    		    },
    		    fail:  function(xhr, textStatus, errorThrown) {
    		      document.getElementById('result').innerHTML = '<div class=\"alert alert-danger\" role=\"alert\">ERROR<br>'+xhr.responseText+'<br></div>';
    		    }
    		    })
    
    	}
    
    	function doLoadLastReference(address)
    	{
    		console.log(address)
    		var base58SenderAccountAddress = address;
    
    		$.ajax({
    			type : "POST",
    			url : nodeUrl + "/index/api.html",
    			data : { type: "get", apiurl: "/addresses/lastreference/" + base58SenderAccountAddress + "/unconfirmed" },
    			async: false,
    			success : function(data) {
    				if(data.type == 'success'){
    					console.log(data)
    					return data.result;
    				}
    
    				if(data.type == 'apicallerror'){
    					return null;
    				}
    			},
    			error: function(){
    				return null;
    			}
    		});
    	}
    var casheBase58addressSeed = '';
    var casheBase58SenderAccountAddress = '';
    var casheBase58RecipientAccountAddress = '';
    var casheTimestamp = '';
    var casheFee = '';
    var casheAmount = '';
    
    
    function doMessageTransaction() {
      text = $('.input-box_text').val();
      address = $('#selected-name option:selected').val();
      room = $('.message-history .active').attr('id').split('-')[0];
    
      var base58SenderAccountSeed = $('#selected-name option:selected').val();
    
      var senderAccountSeed = Base58.decode(base58SenderAccountSeed);
    
      if(senderAccountSeed.length != 32) {
        document.getElementById('result').innerHTML = "<div class=\"alert alert-error\" role=\"alert\">invalid seed<br></div>"
        return;
      }
    
      keyPair = getKeyPairFromSeed(senderAccountSeed);
    
      var base58SenderAccountAddress = getAccountAddressFromPublicKey(keyPair.publicKey);
    
      $('#base58SenderAccountAddress').val(base58SenderAccountAddress);
    
    
      $.ajax({
        type : "POST",
        url : nodeUrl + "/index/api.html",
        data : { type: "get", apiurl: "/addresses/lastreference/" + base58SenderAccountAddress + "/unconfirmed" },
        success : function(data) {
          if(data.type == 'success'){
            console.log(data)
            base58LastReferenceOfAccount =  Base58.decode(data.result);
            var recipientAccountAddress = Base58.decode(room);
    
            if(base58LastReferenceOfAccount == null || base58LastReferenceOfAccount.length != 64) {
              document.getElementById('result').innerHTML = "<div class=\"alert alert-error\" role=\"alert\">invalid reference<br></div>"
              return;
            }
    
            var amount = 1;
            var fee = 1;
            var timestamp = new Date().getTime();
            var messageData = stringtoUTF8Array(text);
            var isText = 1;
            var isEncrypted = 0;
    
            signature = generateSignatureMessageTransaction(keyPair, base58LastReferenceOfAccount, recipientAccountAddress, amount, fee, timestamp, messageData, isText, isEncrypted);
    
            paymentTransactionRaw = generateMessageTransaction(keyPair, base58LastReferenceOfAccount, recipientAccountAddress, amount, fee, timestamp, messageData, isText, isEncrypted, signature);
    
            doProcess(Base58.encode(paymentTransactionRaw));
    
          }
    
          if(data.type == 'apicallerror'){
            return null;
          }
        },
        error: function(){
          return null;
        }
      });
    }
    (function(nacl) {
    'use strict';
    
    // Ported in 2014 by Dmitry Chestnykh and Devi Mandiri.
    // Public domain.
    //
    // Implementation derived from TweetNaCl version 20140427.
    // See for details: http://tweetnacl.cr.yp.to/
    
    var gf = function(init) {
      var i, r = new Float64Array(16);
      if (init) for (i = 0; i < init.length; i++) r[i] = init[i];
      return r;
    };
    
    //  Pluggable, initialized in high-level API below.
    var randombytes = function(/* x, n */) { throw new Error('no PRNG'); };
    
    var _0 = new Uint8Array(16);
    var _9 = new Uint8Array(32); _9[0] = 9;
    
    var gf0 = gf(),
        gf1 = gf([1]),
        _121665 = gf([0xdb41, 1]),
        D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]),
        D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]),
        X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]),
        Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]),
        I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]);
    
    function ts64(x, i, h, l) {
      x[i]   = (h >> 24) & 0xff;
      x[i+1] = (h >> 16) & 0xff;
      x[i+2] = (h >>  8) & 0xff;
      x[i+3] = h & 0xff;
      x[i+4] = (l >> 24)  & 0xff;
      x[i+5] = (l >> 16)  & 0xff;
      x[i+6] = (l >>  8)  & 0xff;
      x[i+7] = l & 0xff;
    }
    
    function vn(x, xi, y, yi, n) {
      var i,d = 0;
      for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i];
      return (1 & ((d - 1) >>> 8)) - 1;
    }
    
    function crypto_verify_16(x, xi, y, yi) {
      return vn(x,xi,y,yi,16);
    }
    
    function crypto_verify_32(x, xi, y, yi) {
      return vn(x,xi,y,yi,32);
    }
    
    function core_salsa20(o, p, k, c) {
      var j0  = c[ 0] & 0xff | (c[ 1] & 0xff)<<8 | (c[ 2] & 0xff)<<16 | (c[ 3] & 0xff)<<24,
          j1  = k[ 0] & 0xff | (k[ 1] & 0xff)<<8 | (k[ 2] & 0xff)<<16 | (k[ 3] & 0xff)<<24,
          j2  = k[ 4] & 0xff | (k[ 5] & 0xff)<<8 | (k[ 6] & 0xff)<<16 | (k[ 7] & 0xff)<<24,
          j3  = k[ 8] & 0xff | (k[ 9] & 0xff)<<8 | (k[10] & 0xff)<<16 | (k[11] & 0xff)<<24,
          j4  = k[12] & 0xff | (k[13] & 0xff)<<8 | (k[14] & 0xff)<<16 | (k[15] & 0xff)<<24,
          j5  = c[ 4] & 0xff | (c[ 5] & 0xff)<<8 | (c[ 6] & 0xff)<<16 | (c[ 7] & 0xff)<<24,
          j6  = p[ 0] & 0xff | (p[ 1] & 0xff)<<8 | (p[ 2] & 0xff)<<16 | (p[ 3] & 0xff)<<24,
          j7  = p[ 4] & 0xff | (p[ 5] & 0xff)<<8 | (p[ 6] & 0xff)<<16 | (p[ 7] & 0xff)<<24,
          j8  = p[ 8] & 0xff | (p[ 9] & 0xff)<<8 | (p[10] & 0xff)<<16 | (p[11] & 0xff)<<24,
          j9  = p[12] & 0xff | (p[13] & 0xff)<<8 | (p[14] & 0xff)<<16 | (p[15] & 0xff)<<24,
          j10 = c[ 8] & 0xff | (c[ 9] & 0xff)<<8 | (c[10] & 0xff)<<16 | (c[11] & 0xff)<<24,
          j11 = k[16] & 0xff | (k[17] & 0xff)<<8 | (k[18] & 0xff)<<16 | (k[19] & 0xff)<<24,
          j12 = k[20] & 0xff | (k[21] & 0xff)<<8 | (k[22] & 0xff)<<16 | (k[23] & 0xff)<<24,
          j13 = k[24] & 0xff | (k[25] & 0xff)<<8 | (k[26] & 0xff)<<16 | (k[27] & 0xff)<<24,
          j14 = k[28] & 0xff | (k[29] & 0xff)<<8 | (k[30] & 0xff)<<16 | (k[31] & 0xff)<<24,
          j15 = c[12] & 0xff | (c[13] & 0xff)<<8 | (c[14] & 0xff)<<16 | (c[15] & 0xff)<<24;
    
      var x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7,
          x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14,
          x15 = j15, u;
    
      for (var i = 0; i < 20; i += 2) {
        u = x0 + x12 | 0;
        x4 ^= u<<7 | u>>>(32-7);
        u = x4 + x0 | 0;
        x8 ^= u<<9 | u>>>(32-9);
        u = x8 + x4 | 0;
        x12 ^= u<<13 | u>>>(32-13);
        u = x12 + x8 | 0;
        x0 ^= u<<18 | u>>>(32-18);
    
        u = x5 + x1 | 0;
        x9 ^= u<<7 | u>>>(32-7);
        u = x9 + x5 | 0;
        x13 ^= u<<9 | u>>>(32-9);
        u = x13 + x9 | 0;
        x1 ^= u<<13 | u>>>(32-13);
        u = x1 + x13 | 0;
        x5 ^= u<<18 | u>>>(32-18);
    
        u = x10 + x6 | 0;
        x14 ^= u<<7 | u>>>(32-7);
        u = x14 + x10 | 0;
        x2 ^= u<<9 | u>>>(32-9);
        u = x2 + x14 | 0;
        x6 ^= u<<13 | u>>>(32-13);
        u = x6 + x2 | 0;
        x10 ^= u<<18 | u>>>(32-18);
    
        u = x15 + x11 | 0;
        x3 ^= u<<7 | u>>>(32-7);
        u = x3 + x15 | 0;
        x7 ^= u<<9 | u>>>(32-9);
        u = x7 + x3 | 0;
        x11 ^= u<<13 | u>>>(32-13);
        u = x11 + x7 | 0;
        x15 ^= u<<18 | u>>>(32-18);
    
        u = x0 + x3 | 0;
        x1 ^= u<<7 | u>>>(32-7);
        u = x1 + x0 | 0;
        x2 ^= u<<9 | u>>>(32-9);
        u = x2 + x1 | 0;
        x3 ^= u<<13 | u>>>(32-13);
        u = x3 + x2 | 0;
        x0 ^= u<<18 | u>>>(32-18);
    
        u = x5 + x4 | 0;
        x6 ^= u<<7 | u>>>(32-7);
        u = x6 + x5 | 0;
        x7 ^= u<<9 | u>>>(32-9);
        u = x7 + x6 | 0;
        x4 ^= u<<13 | u>>>(32-13);
        u = x4 + x7 | 0;
        x5 ^= u<<18 | u>>>(32-18);
    
        u = x10 + x9 | 0;
        x11 ^= u<<7 | u>>>(32-7);
        u = x11 + x10 | 0;
        x8 ^= u<<9 | u>>>(32-9);
        u = x8 + x11 | 0;
        x9 ^= u<<13 | u>>>(32-13);
        u = x9 + x8 | 0;
        x10 ^= u<<18 | u>>>(32-18);
    
        u = x15 + x14 | 0;
        x12 ^= u<<7 | u>>>(32-7);
        u = x12 + x15 | 0;
        x13 ^= u<<9 | u>>>(32-9);
        u = x13 + x12 | 0;
        x14 ^= u<<13 | u>>>(32-13);
        u = x14 + x13 | 0;
        x15 ^= u<<18 | u>>>(32-18);
      }
       x0 =  x0 +  j0 | 0;
       x1 =  x1 +  j1 | 0;
       x2 =  x2 +  j2 | 0;
       x3 =  x3 +  j3 | 0;
       x4 =  x4 +  j4 | 0;
       x5 =  x5 +  j5 | 0;
       x6 =  x6 +  j6 | 0;
       x7 =  x7 +  j7 | 0;
       x8 =  x8 +  j8 | 0;
       x9 =  x9 +  j9 | 0;
      x10 = x10 + j10 | 0;
      x11 = x11 + j11 | 0;
      x12 = x12 + j12 | 0;
      x13 = x13 + j13 | 0;
      x14 = x14 + j14 | 0;
      x15 = x15 + j15 | 0;
    
      o[ 0] = x0 >>>  0 & 0xff;
      o[ 1] = x0 >>>  8 & 0xff;
      o[ 2] = x0 >>> 16 & 0xff;
      o[ 3] = x0 >>> 24 & 0xff;
    
      o[ 4] = x1 >>>  0 & 0xff;
      o[ 5] = x1 >>>  8 & 0xff;
      o[ 6] = x1 >>> 16 & 0xff;
      o[ 7] = x1 >>> 24 & 0xff;
    
      o[ 8] = x2 >>>  0 & 0xff;
      o[ 9] = x2 >>>  8 & 0xff;
      o[10] = x2 >>> 16 & 0xff;
      o[11] = x2 >>> 24 & 0xff;
    
      o[12] = x3 >>>  0 & 0xff;
      o[13] = x3 >>>  8 & 0xff;
      o[14] = x3 >>> 16 & 0xff;
      o[15] = x3 >>> 24 & 0xff;
    
      o[16] = x4 >>>  0 & 0xff;
      o[17] = x4 >>>  8 & 0xff;
      o[18] = x4 >>> 16 & 0xff;
      o[19] = x4 >>> 24 & 0xff;
    
      o[20] = x5 >>>  0 & 0xff;
      o[21] = x5 >>>  8 & 0xff;
      o[22] = x5 >>> 16 & 0xff;
      o[23] = x5 >>> 24 & 0xff;
    
      o[24] = x6 >>>  0 & 0xff;
      o[25] = x6 >>>  8 & 0xff;
      o[26] = x6 >>> 16 & 0xff;
      o[27] = x6 >>> 24 & 0xff;
    
      o[28] = x7 >>>  0 & 0xff;
      o[29] = x7 >>>  8 & 0xff;
      o[30] = x7 >>> 16 & 0xff;
      o[31] = x7 >>> 24 & 0xff;
    
      o[32] = x8 >>>  0 & 0xff;
      o[33] = x8 >>>  8 & 0xff;
      o[34] = x8 >>> 16 & 0xff;
      o[35] = x8 >>> 24 & 0xff;
    
      o[36] = x9 >>>  0 & 0xff;
      o[37] = x9 >>>  8 & 0xff;
      o[38] = x9 >>> 16 & 0xff;
      o[39] = x9 >>> 24 & 0xff;
    
      o[40] = x10 >>>  0 & 0xff;
      o[41] = x10 >>>  8 & 0xff;
      o[42] = x10 >>> 16 & 0xff;
      o[43] = x10 >>> 24 & 0xff;
    
      o[44] = x11 >>>  0 & 0xff;
      o[45] = x11 >>>  8 & 0xff;
      o[46] = x11 >>> 16 & 0xff;
      o[47] = x11 >>> 24 & 0xff;
    
      o[48] = x12 >>>  0 & 0xff;
      o[49] = x12 >>>  8 & 0xff;
      o[50] = x12 >>> 16 & 0xff;
      o[51] = x12 >>> 24 & 0xff;
    
      o[52] = x13 >>>  0 & 0xff;
      o[53] = x13 >>>  8 & 0xff;
      o[54] = x13 >>> 16 & 0xff;
      o[55] = x13 >>> 24 & 0xff;
    
      o[56] = x14 >>>  0 & 0xff;
      o[57] = x14 >>>  8 & 0xff;
      o[58] = x14 >>> 16 & 0xff;
      o[59] = x14 >>> 24 & 0xff;
    
      o[60] = x15 >>>  0 & 0xff;
      o[61] = x15 >>>  8 & 0xff;
      o[62] = x15 >>> 16 & 0xff;
      o[63] = x15 >>> 24 & 0xff;
    }
    
    function core_hsalsa20(o,p,k,c) {
      var j0  = c[ 0] & 0xff | (c[ 1] & 0xff)<<8 | (c[ 2] & 0xff)<<16 | (c[ 3] & 0xff)<<24,
          j1  = k[ 0] & 0xff | (k[ 1] & 0xff)<<8 | (k[ 2] & 0xff)<<16 | (k[ 3] & 0xff)<<24,
          j2  = k[ 4] & 0xff | (k[ 5] & 0xff)<<8 | (k[ 6] & 0xff)<<16 | (k[ 7] & 0xff)<<24,
          j3  = k[ 8] & 0xff | (k[ 9] & 0xff)<<8 | (k[10] & 0xff)<<16 | (k[11] & 0xff)<<24,
          j4  = k[12] & 0xff | (k[13] & 0xff)<<8 | (k[14] & 0xff)<<16 | (k[15] & 0xff)<<24,
          j5  = c[ 4] & 0xff | (c[ 5] & 0xff)<<8 | (c[ 6] & 0xff)<<16 | (c[ 7] & 0xff)<<24,
          j6  = p[ 0] & 0xff | (p[ 1] & 0xff)<<8 | (p[ 2] & 0xff)<<16 | (p[ 3] & 0xff)<<24,
          j7  = p[ 4] & 0xff | (p[ 5] & 0xff)<<8 | (p[ 6] & 0xff)<<16 | (p[ 7] & 0xff)<<24,
          j8  = p[ 8] & 0xff | (p[ 9] & 0xff)<<8 | (p[10] & 0xff)<<16 | (p[11] & 0xff)<<24,
          j9  = p[12] & 0xff | (p[13] & 0xff)<<8 | (p[14] & 0xff)<<16 | (p[15] & 0xff)<<24,
          j10 = c[ 8] & 0xff | (c[ 9] & 0xff)<<8 | (c[10] & 0xff)<<16 | (c[11] & 0xff)<<24,
          j11 = k[16] & 0xff | (k[17] & 0xff)<<8 | (k[18] & 0xff)<<16 | (k[19] & 0xff)<<24,
          j12 = k[20] & 0xff | (k[21] & 0xff)<<8 | (k[22] & 0xff)<<16 | (k[23] & 0xff)<<24,
          j13 = k[24] & 0xff | (k[25] & 0xff)<<8 | (k[26] & 0xff)<<16 | (k[27] & 0xff)<<24,
          j14 = k[28] & 0xff | (k[29] & 0xff)<<8 | (k[30] & 0xff)<<16 | (k[31] & 0xff)<<24,
          j15 = c[12] & 0xff | (c[13] & 0xff)<<8 | (c[14] & 0xff)<<16 | (c[15] & 0xff)<<24;
    
      var x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7,
          x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14,
          x15 = j15, u;
    
      for (var i = 0; i < 20; i += 2) {
        u = x0 + x12 | 0;
        x4 ^= u<<7 | u>>>(32-7);
        u = x4 + x0 | 0;
        x8 ^= u<<9 | u>>>(32-9);
        u = x8 + x4 | 0;
        x12 ^= u<<13 | u>>>(32-13);
        u = x12 + x8 | 0;
        x0 ^= u<<18 | u>>>(32-18);
    
        u = x5 + x1 | 0;
        x9 ^= u<<7 | u>>>(32-7);
        u = x9 + x5 | 0;
        x13 ^= u<<9 | u>>>(32-9);
        u = x13 + x9 | 0;
        x1 ^= u<<13 | u>>>(32-13);
        u = x1 + x13 | 0;
        x5 ^= u<<18 | u>>>(32-18);
    
        u = x10 + x6 | 0;
        x14 ^= u<<7 | u>>>(32-7);
        u = x14 + x10 | 0;
        x2 ^= u<<9 | u>>>(32-9);
        u = x2 + x14 | 0;
        x6 ^= u<<13 | u>>>(32-13);
        u = x6 + x2 | 0;
        x10 ^= u<<18 | u>>>(32-18);
    
        u = x15 + x11 | 0;
        x3 ^= u<<7 | u>>>(32-7);
        u = x3 + x15 | 0;
        x7 ^= u<<9 | u>>>(32-9);
        u = x7 + x3 | 0;
        x11 ^= u<<13 | u>>>(32-13);
        u = x11 + x7 | 0;
        x15 ^= u<<18 | u>>>(32-18);
    
        u = x0 + x3 | 0;
        x1 ^= u<<7 | u>>>(32-7);
        u = x1 + x0 | 0;
        x2 ^= u<<9 | u>>>(32-9);
        u = x2 + x1 | 0;
        x3 ^= u<<13 | u>>>(32-13);
        u = x3 + x2 | 0;
        x0 ^= u<<18 | u>>>(32-18);
    
        u = x5 + x4 | 0;
        x6 ^= u<<7 | u>>>(32-7);
        u = x6 + x5 | 0;
        x7 ^= u<<9 | u>>>(32-9);
        u = x7 + x6 | 0;
        x4 ^= u<<13 | u>>>(32-13);
        u = x4 + x7 | 0;
        x5 ^= u<<18 | u>>>(32-18);
    
        u = x10 + x9 | 0;
        x11 ^= u<<7 | u>>>(32-7);
        u = x11 + x10 | 0;
        x8 ^= u<<9 | u>>>(32-9);
        u = x8 + x11 | 0;
        x9 ^= u<<13 | u>>>(32-13);
        u = x9 + x8 | 0;
        x10 ^= u<<18 | u>>>(32-18);
    
        u = x15 + x14 | 0;
        x12 ^= u<<7 | u>>>(32-7);
        u = x12 + x15 | 0;
        x13 ^= u<<9 | u>>>(32-9);
        u = x13 + x12 | 0;
        x14 ^= u<<13 | u>>>(32-13);
        u = x14 + x13 | 0;
        x15 ^= u<<18 | u>>>(32-18);
      }
    
      o[ 0] = x0 >>>  0 & 0xff;
      o[ 1] = x0 >>>  8 & 0xff;
      o[ 2] = x0 >>> 16 & 0xff;
      o[ 3] = x0 >>> 24 & 0xff;
    
      o[ 4] = x5 >>>  0 & 0xff;
      o[ 5] = x5 >>>  8 & 0xff;
      o[ 6] = x5 >>> 16 & 0xff;
      o[ 7] = x5 >>> 24 & 0xff;
    
      o[ 8] = x10 >>>  0 & 0xff;
      o[ 9] = x10 >>>  8 & 0xff;
      o[10] = x10 >>> 16 & 0xff;
      o[11] = x10 >>> 24 & 0xff;
    
      o[12] = x15 >>>  0 & 0xff;
      o[13] = x15 >>>  8 & 0xff;
      o[14] = x15 >>> 16 & 0xff;
      o[15] = x15 >>> 24 & 0xff;
    
      o[16] = x6 >>>  0 & 0xff;
      o[17] = x6 >>>  8 & 0xff;
      o[18] = x6 >>> 16 & 0xff;
      o[19] = x6 >>> 24 & 0xff;
    
      o[20] = x7 >>>  0 & 0xff;
      o[21] = x7 >>>  8 & 0xff;
      o[22] = x7 >>> 16 & 0xff;
      o[23] = x7 >>> 24 & 0xff;
    
      o[24] = x8 >>>  0 & 0xff;
      o[25] = x8 >>>  8 & 0xff;
      o[26] = x8 >>> 16 & 0xff;
      o[27] = x8 >>> 24 & 0xff;
    
      o[28] = x9 >>>  0 & 0xff;
      o[29] = x9 >>>  8 & 0xff;
      o[30] = x9 >>> 16 & 0xff;
      o[31] = x9 >>> 24 & 0xff;
    }
    
    function crypto_core_salsa20(out,inp,k,c) {
      core_salsa20(out,inp,k,c);
    }
    
    function crypto_core_hsalsa20(out,inp,k,c) {
      core_hsalsa20(out,inp,k,c);
    }
    
    var sigma = new Uint8Array([101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107]);
                // "expand 32-byte k"
    
    function crypto_stream_salsa20_xor(c,cpos,m,mpos,b,n,k) {
      var z = new Uint8Array(16), x = new Uint8Array(64);
      var u, i;
      for (i = 0; i < 16; i++) z[i] = 0;
      for (i = 0; i < 8; i++) z[i] = n[i];
      while (b >= 64) {
        crypto_core_salsa20(x,z,k,sigma);
        for (i = 0; i < 64; i++) c[cpos+i] = m[mpos+i] ^ x[i];
        u = 1;
        for (i = 8; i < 16; i++) {
          u = u + (z[i] & 0xff) | 0;
          z[i] = u & 0xff;
          u >>>= 8;
        }
        b -= 64;
        cpos += 64;
        mpos += 64;
      }
      if (b > 0) {
        crypto_core_salsa20(x,z,k,sigma);
        for (i = 0; i < b; i++) c[cpos+i] = m[mpos+i] ^ x[i];
      }
      return 0;
    }
    
    function crypto_stream_salsa20(c,cpos,b,n,k) {
      var z = new Uint8Array(16), x = new Uint8Array(64);
      var u, i;
      for (i = 0; i < 16; i++) z[i] = 0;
      for (i = 0; i < 8; i++) z[i] = n[i];
      while (b >= 64) {
        crypto_core_salsa20(x,z,k,sigma);
        for (i = 0; i < 64; i++) c[cpos+i] = x[i];
        u = 1;
        for (i = 8; i < 16; i++) {
          u = u + (z[i] & 0xff) | 0;
          z[i] = u & 0xff;
          u >>>= 8;
        }
        b -= 64;
        cpos += 64;
      }
      if (b > 0) {
        crypto_core_salsa20(x,z,k,sigma);
        for (i = 0; i < b; i++) c[cpos+i] = x[i];
      }
      return 0;
    }
    
    function crypto_stream(c,cpos,d,n,k) {
      var s = new Uint8Array(32);
      crypto_core_hsalsa20(s,n,k,sigma);
      var sn = new Uint8Array(8);
      for (var i = 0; i < 8; i++) sn[i] = n[i+16];
      return crypto_stream_salsa20(c,cpos,d,sn,s);
    }
    
    function crypto_stream_xor(c,cpos,m,mpos,d,n,k) {
      var s = new Uint8Array(32);
      crypto_core_hsalsa20(s,n,k,sigma);
      var sn = new Uint8Array(8);
      for (var i = 0; i < 8; i++) sn[i] = n[i+16];
      return crypto_stream_salsa20_xor(c,cpos,m,mpos,d,sn,s);
    }
    
    /*
    * Port of Andrew Moon's Poly1305-donna-16. Public domain.
    * https://github.com/floodyberry/poly1305-donna
    */
    
    var poly1305 = function(key) {
      this.buffer = new Uint8Array(16);
      this.r = new Uint16Array(10);
      this.h = new Uint16Array(10);
      this.pad = new Uint16Array(8);
      this.leftover = 0;
      this.fin = 0;
    
      var t0, t1, t2, t3, t4, t5, t6, t7;
    
      t0 = key[ 0] & 0xff | (key[ 1] & 0xff) << 8; this.r[0] = ( t0                     ) & 0x1fff;
      t1 = key[ 2] & 0xff | (key[ 3] & 0xff) << 8; this.r[1] = ((t0 >>> 13) | (t1 <<  3)) & 0x1fff;
      t2 = key[ 4] & 0xff | (key[ 5] & 0xff) << 8; this.r[2] = ((t1 >>> 10) | (t2 <<  6)) & 0x1f03;
      t3 = key[ 6] & 0xff | (key[ 7] & 0xff) << 8; this.r[3] = ((t2 >>>  7) | (t3 <<  9)) & 0x1fff;
      t4 = key[ 8] & 0xff | (key[ 9] & 0xff) << 8; this.r[4] = ((t3 >>>  4) | (t4 << 12)) & 0x00ff;
      this.r[5] = ((t4 >>>  1)) & 0x1ffe;
      t5 = key[10] & 0xff | (key[11] & 0xff) << 8; this.r[6] = ((t4 >>> 14) | (t5 <<  2)) & 0x1fff;
      t6 = key[12] & 0xff | (key[13] & 0xff) << 8; this.r[7] = ((t5 >>> 11) | (t6 <<  5)) & 0x1f81;
      t7 = key[14] & 0xff | (key[15] & 0xff) << 8; this.r[8] = ((t6 >>>  8) | (t7 <<  8)) & 0x1fff;
      this.r[9] = ((t7 >>>  5)) & 0x007f;
    
      this.pad[0] = key[16] & 0xff | (key[17] & 0xff) << 8;
      this.pad[1] = key[18] & 0xff | (key[19] & 0xff) << 8;
      this.pad[2] = key[20] & 0xff | (key[21] & 0xff) << 8;
      this.pad[3] = key[22] & 0xff | (key[23] & 0xff) << 8;
      this.pad[4] = key[24] & 0xff | (key[25] & 0xff) << 8;
      this.pad[5] = key[26] & 0xff | (key[27] & 0xff) << 8;
      this.pad[6] = key[28] & 0xff | (key[29] & 0xff) << 8;
      this.pad[7] = key[30] & 0xff | (key[31] & 0xff) << 8;
    };
    
    poly1305.prototype.blocks = function(m, mpos, bytes) {
      var hibit = this.fin ? 0 : (1 << 11);
      var t0, t1, t2, t3, t4, t5, t6, t7, c;
      var d0, d1, d2, d3, d4, d5, d6, d7, d8, d9;
    
      var h0 = this.h[0],
          h1 = this.h[1],
          h2 = this.h[2],
          h3 = this.h[3],
          h4 = this.h[4],
          h5 = this.h[5],
          h6 = this.h[6],
          h7 = this.h[7],
          h8 = this.h[8],
          h9 = this.h[9];
    
      var r0 = this.r[0],
          r1 = this.r[1],
          r2 = this.r[2],
          r3 = this.r[3],
          r4 = this.r[4],
          r5 = this.r[5],
          r6 = this.r[6],
          r7 = this.r[7],
          r8 = this.r[8],
          r9 = this.r[9];
    
      while (bytes >= 16) {
        t0 = m[mpos+ 0] & 0xff | (m[mpos+ 1] & 0xff) << 8; h0 += ( t0                     ) & 0x1fff;
        t1 = m[mpos+ 2] & 0xff | (m[mpos+ 3] & 0xff) << 8; h1 += ((t0 >>> 13) | (t1 <<  3)) & 0x1fff;
        t2 = m[mpos+ 4] & 0xff | (m[mpos+ 5] & 0xff) << 8; h2 += ((t1 >>> 10) | (t2 <<  6)) & 0x1fff;
        t3 = m[mpos+ 6] & 0xff | (m[mpos+ 7] & 0xff) << 8; h3 += ((t2 >>>  7) | (t3 <<  9)) & 0x1fff;
        t4 = m[mpos+ 8] & 0xff | (m[mpos+ 9] & 0xff) << 8; h4 += ((t3 >>>  4) | (t4 << 12)) & 0x1fff;
        h5 += ((t4 >>>  1)) & 0x1fff;
        t5 = m[mpos+10] & 0xff | (m[mpos+11] & 0xff) << 8; h6 += ((t4 >>> 14) | (t5 <<  2)) & 0x1fff;
        t6 = m[mpos+12] & 0xff | (m[mpos+13] & 0xff) << 8; h7 += ((t5 >>> 11) | (t6 <<  5)) & 0x1fff;
        t7 = m[mpos+14] & 0xff | (m[mpos+15] & 0xff) << 8; h8 += ((t6 >>>  8) | (t7 <<  8)) & 0x1fff;
        h9 += ((t7 >>> 5)) | hibit;
    
        c = 0;
    
        d0 = c;
        d0 += h0 * r0;
        d0 += h1 * (5 * r9);
        d0 += h2 * (5 * r8);
        d0 += h3 * (5 * r7);
        d0 += h4 * (5 * r6);
        c = (d0 >>> 13); d0 &= 0x1fff;
        d0 += h5 * (5 * r5);
        d0 += h6 * (5 * r4);
        d0 += h7 * (5 * r3);
        d0 += h8 * (5 * r2);
        d0 += h9 * (5 * r1);
        c += (d0 >>> 13); d0 &= 0x1fff;
    
        d1 = c;
        d1 += h0 * r1;
        d1 += h1 * r0;
        d1 += h2 * (5 * r9);
        d1 += h3 * (5 * r8);
        d1 += h4 * (5 * r7);
        c = (d1 >>> 13); d1 &= 0x1fff;
        d1 += h5 * (5 * r6);
        d1 += h6 * (5 * r5);
        d1 += h7 * (5 * r4);
        d1 += h8 * (5 * r3);
        d1 += h9 * (5 * r2);
        c += (d1 >>> 13); d1 &= 0x1fff;
    
        d2 = c;
        d2 += h0 * r2;
        d2 += h1 * r1;
        d2 += h2 * r0;
        d2 += h3 * (5 * r9);
        d2 += h4 * (5 * r8);
        c = (d2 >>> 13); d2 &= 0x1fff;
        d2 += h5 * (5 * r7);
        d2 += h6 * (5 * r6);
        d2 += h7 * (5 * r5);
        d2 += h8 * (5 * r4);
        d2 += h9 * (5 * r3);
        c += (d2 >>> 13); d2 &= 0x1fff;
    
        d3 = c;
        d3 += h0 * r3;
        d3 += h1 * r2;
        d3 += h2 * r1;
        d3 += h3 * r0;
        d3 += h4 * (5 * r9);
        c = (d3 >>> 13); d3 &= 0x1fff;
        d3 += h5 * (5 * r8);
        d3 += h6 * (5 * r7);
        d3 += h7 * (5 * r6);
        d3 += h8 * (5 * r5);
        d3 += h9 * (5 * r4);
        c += (d3 >>> 13); d3 &= 0x1fff;
    
        d4 = c;
        d4 += h0 * r4;
        d4 += h1 * r3;
        d4 += h2 * r2;
        d4 += h3 * r1;
        d4 += h4 * r0;
        c = (d4 >>> 13); d4 &= 0x1fff;
        d4 += h5 * (5 * r9);
        d4 += h6 * (5 * r8);
        d4 += h7 * (5 * r7);
        d4 += h8 * (5 * r6);
        d4 += h9 * (5 * r5);
        c += (d4 >>> 13); d4 &= 0x1fff;
    
        d5 = c;
        d5 += h0 * r5;
        d5 += h1 * r4;
        d5 += h2 * r3;
        d5 += h3 * r2;
        d5 += h4 * r1;
        c = (d5 >>> 13); d5 &= 0x1fff;
        d5 += h5 * r0;
        d5 += h6 * (5 * r9);
        d5 += h7 * (5 * r8);
        d5 += h8 * (5 * r7);
        d5 += h9 * (5 * r6);
        c += (d5 >>> 13); d5 &= 0x1fff;
    
        d6 = c;
        d6 += h0 * r6;
        d6 += h1 * r5;
        d6 += h2 * r4;
        d6 += h3 * r3;
        d6 += h4 * r2;
        c = (d6 >>> 13); d6 &= 0x1fff;
        d6 += h5 * r1;
        d6 += h6 * r0;
        d6 += h7 * (5 * r9);
        d6 += h8 * (5 * r8);
        d6 += h9 * (5 * r7);
        c += (d6 >>> 13); d6 &= 0x1fff;
    
        d7 = c;
        d7 += h0 * r7;
        d7 += h1 * r6;
        d7 += h2 * r5;
        d7 += h3 * r4;
        d7 += h4 * r3;
        c = (d7 >>> 13); d7 &= 0x1fff;
        d7 += h5 * r2;
        d7 += h6 * r1;
        d7 += h7 * r0;
        d7 += h8 * (5 * r9);
        d7 += h9 * (5 * r8);
        c += (d7 >>> 13); d7 &= 0x1fff;
    
        d8 = c;
        d8 += h0 * r8;
        d8 += h1 * r7;
        d8 += h2 * r6;
        d8 += h3 * r5;
        d8 += h4 * r4;
        c = (d8 >>> 13); d8 &= 0x1fff;
        d8 += h5 * r3;
        d8 += h6 * r2;
        d8 += h7 * r1;
        d8 += h8 * r0;
        d8 += h9 * (5 * r9);
        c += (d8 >>> 13); d8 &= 0x1fff;
    
        d9 = c;
        d9 += h0 * r9;
        d9 += h1 * r8;
        d9 += h2 * r7;
        d9 += h3 * r6;
        d9 += h4 * r5;
        c = (d9 >>> 13); d9 &= 0x1fff;
        d9 += h5 * r4;
        d9 += h6 * r3;
        d9 += h7 * r2;
        d9 += h8 * r1;
        d9 += h9 * r0;
        c += (d9 >>> 13); d9 &= 0x1fff;
    
        c = (((c << 2) + c)) | 0;
        c = (c + d0) | 0;
        d0 = c & 0x1fff;
        c = (c >>> 13);
        d1 += c;
    
        h0 = d0;
        h1 = d1;
        h2 = d2;
        h3 = d3;
        h4 = d4;
        h5 = d5;
        h6 = d6;
        h7 = d7;
        h8 = d8;
        h9 = d9;
    
        mpos += 16;
        bytes -= 16;
      }
      this.h[0] = h0;
      this.h[1] = h1;
      this.h[2] = h2;
      this.h[3] = h3;
      this.h[4] = h4;
      this.h[5] = h5;
      this.h[6] = h6;
      this.h[7] = h7;
      this.h[8] = h8;
      this.h[9] = h9;
    };
    
    poly1305.prototype.finish = function(mac, macpos) {
      var g = new Uint16Array(10);
      var c, mask, f, i;
    
      if (this.leftover) {
        i = this.leftover;
        this.buffer[i++] = 1;
        for (; i < 16; i++) this.buffer[i] = 0;
        this.fin = 1;
        this.blocks(this.buffer, 0, 16);
      }
    
      c = this.h[1] >>> 13;
      this.h[1] &= 0x1fff;
      for (i = 2; i < 10; i++) {
        this.h[i] += c;
        c = this.h[i] >>> 13;
        this.h[i] &= 0x1fff;
      }
      this.h[0] += (c * 5);
      c = this.h[0] >>> 13;
      this.h[0] &= 0x1fff;
      this.h[1] += c;
      c = this.h[1] >>> 13;
      this.h[1] &= 0x1fff;
      this.h[2] += c;
    
      g[0] = this.h[0] + 5;
      c = g[0] >>> 13;
      g[0] &= 0x1fff;
      for (i = 1; i < 10; i++) {
        g[i] = this.h[i] + c;
        c = g[i] >>> 13;
        g[i] &= 0x1fff;
      }
      g[9] -= (1 << 13);
    
      mask = (g[9] >>> ((2 * 8) - 1)) - 1;
      for (i = 0; i < 10; i++) g[i] &= mask;
      mask = ~mask;
      for (i = 0; i < 10; i++) this.h[i] = (this.h[i] & mask) | g[i];
    
      this.h[0] = ((this.h[0]       ) | (this.h[1] << 13)                    ) & 0xffff;
      this.h[1] = ((this.h[1] >>>  3) | (this.h[2] << 10)                    ) & 0xffff;
      this.h[2] = ((this.h[2] >>>  6) | (this.h[3] <<  7)                    ) & 0xffff;
      this.h[3] = ((this.h[3] >>>  9) | (this.h[4] <<  4)                    ) & 0xffff;
      this.h[4] = ((this.h[4] >>> 12) | (this.h[5] <<  1) | (this.h[6] << 14)) & 0xffff;
      this.h[5] = ((this.h[6] >>>  2) | (this.h[7] << 11)                    ) & 0xffff;
      this.h[6] = ((this.h[7] >>>  5) | (this.h[8] <<  8)                    ) & 0xffff;
      this.h[7] = ((this.h[8] >>>  8) | (this.h[9] <<  5)                    ) & 0xffff;
    
      f = this.h[0] + this.pad[0];
      this.h[0] = f & 0xffff;
      for (i = 1; i < 8; i++) {
        f = (((this.h[i] + this.pad[i]) | 0) + (f >>> 16)) | 0;
        this.h[i] = f & 0xffff;
      }
    
      mac[macpos+ 0] = (this.h[0] >>> 0) & 0xff;
      mac[macpos+ 1] = (this.h[0] >>> 8) & 0xff;
      mac[macpos+ 2] = (this.h[1] >>> 0) & 0xff;
      mac[macpos+ 3] = (this.h[1] >>> 8) & 0xff;
      mac[macpos+ 4] = (this.h[2] >>> 0) & 0xff;
      mac[macpos+ 5] = (this.h[2] >>> 8) & 0xff;
      mac[macpos+ 6] = (this.h[3] >>> 0) & 0xff;
      mac[macpos+ 7] = (this.h[3] >>> 8) & 0xff;
      mac[macpos+ 8] = (this.h[4] >>> 0) & 0xff;
      mac[macpos+ 9] = (this.h[4] >>> 8) & 0xff;
      mac[macpos+10] = (this.h[5] >>> 0) & 0xff;
      mac[macpos+11] = (this.h[5] >>> 8) & 0xff;
      mac[macpos+12] = (this.h[6] >>> 0) & 0xff;
      mac[macpos+13] = (this.h[6] >>> 8) & 0xff;
      mac[macpos+14] = (this.h[7] >>> 0) & 0xff;
      mac[macpos+15] = (this.h[7] >>> 8) & 0xff;
    };
    
    poly1305.prototype.update = function(m, mpos, bytes) {
      var i, want;
    
      if (this.leftover) {
        want = (16 - this.leftover);
        if (want > bytes)
          want = bytes;
        for (i = 0; i < want; i++)
          this.buffer[this.leftover + i] = m[mpos+i];
        bytes -= want;
        mpos += want;
        this.leftover += want;
        if (this.leftover < 16)
          return;
        this.blocks(this.buffer, 0, 16);
        this.leftover = 0;
      }
    
      if (bytes >= 16) {
        want = bytes - (bytes % 16);
        this.blocks(m, mpos, want);
        mpos += want;
        bytes -= want;
      }
    
      if (bytes) {
        for (i = 0; i < bytes; i++)
          this.buffer[this.leftover + i] = m[mpos+i];
        this.leftover += bytes;
      }
    };
    
    function crypto_onetimeauth(out, outpos, m, mpos, n, k) {
      var s = new poly1305(k);
      s.update(m, mpos, n);
      s.finish(out, outpos);
      return 0;
    }
    
    function crypto_onetimeauth_verify(h, hpos, m, mpos, n, k) {
      var x = new Uint8Array(16);
      crypto_onetimeauth(x,0,m,mpos,n,k);
      return crypto_verify_16(h,hpos,x,0);
    }
    
    function crypto_secretbox(c,m,d,n,k) {
      var i;
      if (d < 32) return -1;
      crypto_stream_xor(c,0,m,0,d,n,k);
      crypto_onetimeauth(c, 16, c, 32, d - 32, c);
      for (i = 0; i < 16; i++) c[i] = 0;
      return 0;
    }
    
    function crypto_secretbox_open(m,c,d,n,k) {
      var i;
      var x = new Uint8Array(32);
      if (d < 32) return -1;
      crypto_stream(x,0,32,n,k);
      if (crypto_onetimeauth_verify(c, 16,c, 32,d - 32,x) !== 0) return -1;
      crypto_stream_xor(m,0,c,0,d,n,k);
      for (i = 0; i < 32; i++) m[i] = 0;
      return 0;
    }
    
    function set25519(r, a) {
      var i;
      for (i = 0; i < 16; i++) r[i] = a[i]|0;
    }
    
    function car25519(o) {
      var i, v, c = 1;
      for (i = 0; i < 16; i++) {
        v = o[i] + c + 65535;
        c = Math.floor(v / 65536);
        o[i] = v - c * 65536;
      }
      o[0] += c-1 + 37 * (c-1);
    }
    
    function sel25519(p, q, b) {
      var t, c = ~(b-1);
      for (var i = 0; i < 16; i++) {
        t = c & (p[i] ^ q[i]);
        p[i] ^= t;
        q[i] ^= t;
      }
    }
    
    function pack25519(o, n) {
      var i, j, b;
      var m = gf(), t = gf();
      for (i = 0; i < 16; i++) t[i] = n[i];
      car25519(t);
      car25519(t);
      car25519(t);
      for (j = 0; j < 2; j++) {
        m[0] = t[0] - 0xffed;
        for (i = 1; i < 15; i++) {
          m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1);
          m[i-1] &= 0xffff;
        }
        m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1);
        b = (m[15]>>16) & 1;
        m[14] &= 0xffff;
        sel25519(t, m, 1-b);
      }
      for (i = 0; i < 16; i++) {
        o[2*i] = t[i] & 0xff;
        o[2*i+1] = t[i]>>8;
      }
    }
    
    function neq25519(a, b) {
      var c = new Uint8Array(32), d = new Uint8Array(32);
      pack25519(c, a);
      pack25519(d, b);
      return crypto_verify_32(c, 0, d, 0);
    }
    
    function par25519(a) {
      var d = new Uint8Array(32);
      pack25519(d, a);
      return d[0] & 1;
    }
    
    function unpack25519(o, n) {
      var i;
      for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8);
      o[15] &= 0x7fff;
    }
    
    function A(o, a, b) {
      for (var i = 0; i < 16; i++) o[i] = a[i] + b[i];
    }
    
    function Z(o, a, b) {
      for (var i = 0; i < 16; i++) o[i] = a[i] - b[i];
    }
    
    function M(o, a, b) {
      var v, c,
         t0 = 0,  t1 = 0,  t2 = 0,  t3 = 0,  t4 = 0,  t5 = 0,  t6 = 0,  t7 = 0,
         t8 = 0,  t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0,
        t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0,
        t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0,
        b0 = b[0],
        b1 = b[1],
        b2 = b[2],
        b3 = b[3],
        b4 = b[4],
        b5 = b[5],
        b6 = b[6],
        b7 = b[7],
        b8 = b[8],
        b9 = b[9],
        b10 = b[10],
        b11 = b[11],
        b12 = b[12],
        b13 = b[13],
        b14 = b[14],
        b15 = b[15];
    
      v = a[0];
      t0 += v * b0;
      t1 += v * b1;
      t2 += v * b2;
      t3 += v * b3;
      t4 += v * b4;
      t5 += v * b5;
      t6 += v * b6;
      t7 += v * b7;
      t8 += v * b8;
      t9 += v * b9;
      t10 += v * b10;
      t11 += v * b11;
      t12 += v * b12;
      t13 += v * b13;
      t14 += v * b14;
      t15 += v * b15;
      v = a[1];
      t1 += v * b0;
      t2 += v * b1;
      t3 += v * b2;
      t4 += v * b3;
      t5 += v * b4;
      t6 += v * b5;
      t7 += v * b6;
      t8 += v * b7;
      t9 += v * b8;
      t10 += v * b9;
      t11 += v * b10;
      t12 += v * b11;
      t13 += v * b12;
      t14 += v * b13;
      t15 += v * b14;
      t16 += v * b15;
      v = a[2];
      t2 += v * b0;
      t3 += v * b1;
      t4 += v * b2;
      t5 += v * b3;
      t6 += v * b4;
      t7 += v * b5;
      t8 += v * b6;
      t9 += v * b7;
      t10 += v * b8;
      t11 += v * b9;
      t12 += v * b10;
      t13 += v * b11;
      t14 += v * b12;
      t15 += v * b13;
      t16 += v * b14;
      t17 += v * b15;
      v = a[3];
      t3 += v * b0;
      t4 += v * b1;
      t5 += v * b2;
      t6 += v * b3;
      t7 += v * b4;
      t8 += v * b5;
      t9 += v * b6;
      t10 += v * b7;
      t11 += v * b8;
      t12 += v * b9;
      t13 += v * b10;
      t14 += v * b11;
      t15 += v * b12;
      t16 += v * b13;
      t17 += v * b14;
      t18 += v * b15;
      v = a[4];
      t4 += v * b0;
      t5 += v * b1;
      t6 += v * b2;
      t7 += v * b3;
      t8 += v * b4;
      t9 += v * b5;
      t10 += v * b6;
      t11 += v * b7;
      t12 += v * b8;
      t13 += v * b9;
      t14 += v * b10;
      t15 += v * b11;
      t16 += v * b12;
      t17 += v * b13;
      t18 += v * b14;
      t19 += v * b15;
      v = a[5];
      t5 += v * b0;
      t6 += v * b1;
      t7 += v * b2;
      t8 += v * b3;
      t9 += v * b4;
      t10 += v * b5;
      t11 += v * b6;
      t12 += v * b7;
      t13 += v * b8;
      t14 += v * b9;
      t15 += v * b10;
      t16 += v * b11;
      t17 += v * b12;
      t18 += v * b13;
      t19 += v * b14;
      t20 += v * b15;
      v = a[6];
      t6 += v * b0;
      t7 += v * b1;
      t8 += v * b2;
      t9 += v * b3;
      t10 += v * b4;
      t11 += v * b5;
      t12 += v * b6;
      t13 += v * b7;
      t14 += v * b8;
      t15 += v * b9;
      t16 += v * b10;
      t17 += v * b11;
      t18 += v * b12;
      t19 += v * b13;
      t20 += v * b14;
      t21 += v * b15;
      v = a[7];
      t7 += v * b0;
      t8 += v * b1;
      t9 += v * b2;
      t10 += v * b3;
      t11 += v * b4;
      t12 += v * b5;
      t13 += v * b6;
      t14 += v * b7;
      t15 += v * b8;
      t16 += v * b9;
      t17 += v * b10;
      t18 += v * b11;
      t19 += v * b12;
      t20 += v * b13;
      t21 += v * b14;
      t22 += v * b15;
      v = a[8];
      t8 += v * b0;
      t9 += v * b1;
      t10 += v * b2;
      t11 += v * b3;
      t12 += v * b4;
      t13 += v * b5;
      t14 += v * b6;
      t15 += v * b7;
      t16 += v * b8;
      t17 += v * b9;
      t18 += v * b10;
      t19 += v * b11;
      t20 += v * b12;
      t21 += v * b13;
      t22 += v * b14;
      t23 += v * b15;
      v = a[9];
      t9 += v * b0;
      t10 += v * b1;
      t11 += v * b2;
      t12 += v * b3;
      t13 += v * b4;
      t14 += v * b5;
      t15 += v * b6;
      t16 += v * b7;
      t17 += v * b8;
      t18 += v * b9;
      t19 += v * b10;
      t20 += v * b11;
      t21 += v * b12;
      t22 += v * b13;
      t23 += v * b14;
      t24 += v * b15;
      v = a[10];
      t10 += v * b0;
      t11 += v * b1;
      t12 += v * b2;
      t13 += v * b3;
      t14 += v * b4;
      t15 += v * b5;
      t16 += v * b6;
      t17 += v * b7;
      t18 += v * b8;
      t19 += v * b9;
      t20 += v * b10;
      t21 += v * b11;
      t22 += v * b12;
      t23 += v * b13;
      t24 += v * b14;
      t25 += v * b15;
      v = a[11];
      t11 += v * b0;
      t12 += v * b1;
      t13 += v * b2;
      t14 += v * b3;
      t15 += v * b4;
      t16 += v * b5;
      t17 += v * b6;
      t18 += v * b7;
      t19 += v * b8;
      t20 += v * b9;
      t21 += v * b10;
      t22 += v * b11;
      t23 += v * b12;
      t24 += v * b13;
      t25 += v * b14;
      t26 += v * b15;
      v = a[12];
      t12 += v * b0;
      t13 += v * b1;
      t14 += v * b2;
      t15 += v * b3;
      t16 += v * b4;
      t17 += v * b5;
      t18 += v * b6;
      t19 += v * b7;
      t20 += v * b8;
      t21 += v * b9;
      t22 += v * b10;
      t23 += v * b11;
      t24 += v * b12;
      t25 += v * b13;
      t26 += v * b14;
      t27 += v * b15;
      v = a[13];
      t13 += v * b0;
      t14 += v * b1;
      t15 += v * b2;
      t16 += v * b3;
      t17 += v * b4;
      t18 += v * b5;
      t19 += v * b6;
      t20 += v * b7;
      t21 += v * b8;
      t22 += v * b9;
      t23 += v * b10;
      t24 += v * b11;
      t25 += v * b12;
      t26 += v * b13;
      t27 += v * b14;
      t28 += v * b15;
      v = a[14];
      t14 += v * b0;
      t15 += v * b1;
      t16 += v * b2;
      t17 += v * b3;
      t18 += v * b4;
      t19 += v * b5;
      t20 += v * b6;
      t21 += v * b7;
      t22 += v * b8;
      t23 += v * b9;
      t24 += v * b10;
      t25 += v * b11;
      t26 += v * b12;
      t27 += v * b13;
      t28 += v * b14;
      t29 += v * b15;
      v = a[15];
      t15 += v * b0;
      t16 += v * b1;
      t17 += v * b2;
      t18 += v * b3;
      t19 += v * b4;
      t20 += v * b5;
      t21 += v * b6;
      t22 += v * b7;
      t23 += v * b8;
      t24 += v * b9;
      t25 += v * b10;
      t26 += v * b11;
      t27 += v * b12;
      t28 += v * b13;
      t29 += v * b14;
      t30 += v * b15;
    
      t0  += 38 * t16;
      t1  += 38 * t17;
      t2  += 38 * t18;
      t3  += 38 * t19;
      t4  += 38 * t20;
      t5  += 38 * t21;
      t6  += 38 * t22;
      t7  += 38 * t23;
      t8  += 38 * t24;
      t9  += 38 * t25;
      t10 += 38 * t26;
      t11 += 38 * t27;
      t12 += 38 * t28;
      t13 += 38 * t29;
      t14 += 38 * t30;
      // t15 left as is
    
      // first car
      c = 1;
      v =  t0 + c + 65535; c = Math.floor(v / 65536);  t0 = v - c * 65536;
      v =  t1 + c + 65535; c = Math.floor(v / 65536);  t1 = v - c * 65536;
      v =  t2 + c + 65535; c = Math.floor(v / 65536);  t2 = v - c * 65536;
      v =  t3 + c + 65535; c = Math.floor(v / 65536);  t3 = v - c * 65536;
      v =  t4 + c + 65535; c = Math.floor(v / 65536);  t4 = v - c * 65536;
      v =  t5 + c + 65535; c = Math.floor(v / 65536);  t5 = v - c * 65536;
      v =  t6 + c + 65535; c = Math.floor(v / 65536);  t6 = v - c * 65536;
      v =  t7 + c + 65535; c = Math.floor(v / 65536);  t7 = v - c * 65536;
      v =  t8 + c + 65535; c = Math.floor(v / 65536);  t8 = v - c * 65536;
      v =  t9 + c + 65535; c = Math.floor(v / 65536);  t9 = v - c * 65536;
      v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
      v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
      v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
      v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
      v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
      v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
      t0 += c-1 + 37 * (c-1);
    
      // second car
      c = 1;
      v =  t0 + c + 65535; c = Math.floor(v / 65536);  t0 = v - c * 65536;
      v =  t1 + c + 65535; c = Math.floor(v / 65536);  t1 = v - c * 65536;
      v =  t2 + c + 65535; c = Math.floor(v / 65536);  t2 = v - c * 65536;
      v =  t3 + c + 65535; c = Math.floor(v / 65536);  t3 = v - c * 65536;
      v =  t4 + c + 65535; c = Math.floor(v / 65536);  t4 = v - c * 65536;
      v =  t5 + c + 65535; c = Math.floor(v / 65536);  t5 = v - c * 65536;
      v =  t6 + c + 65535; c = Math.floor(v / 65536);  t6 = v - c * 65536;
      v =  t7 + c + 65535; c = Math.floor(v / 65536);  t7 = v - c * 65536;
      v =  t8 + c + 65535; c = Math.floor(v / 65536);  t8 = v - c * 65536;
      v =  t9 + c + 65535; c = Math.floor(v / 65536);  t9 = v - c * 65536;
      v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
      v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
      v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
      v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
      v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
      v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
      t0 += c-1 + 37 * (c-1);
    
      o[ 0] = t0;
      o[ 1] = t1;
      o[ 2] = t2;
      o[ 3] = t3;
      o[ 4] = t4;
      o[ 5] = t5;
      o[ 6] = t6;
      o[ 7] = t7;
      o[ 8] = t8;
      o[ 9] = t9;
      o[10] = t10;
      o[11] = t11;
      o[12] = t12;
      o[13] = t13;
      o[14] = t14;
      o[15] = t15;
    }
    
    function S(o, a) {
      M(o, a, a);
    }
    
    function inv25519(o, i) {
      var c = gf();
      var a;
      for (a = 0; a < 16; a++) c[a] = i[a];
      for (a = 253; a >= 0; a--) {
        S(c, c);
        if(a !== 2 && a !== 4) M(c, c, i);
      }
      for (a = 0; a < 16; a++) o[a] = c[a];
    }
    
    function pow2523(o, i) {
      var c = gf();
      var a;
      for (a = 0; a < 16; a++) c[a] = i[a];
      for (a = 250; a >= 0; a--) {
          S(c, c);
          if(a !== 1) M(c, c, i);
      }
      for (a = 0; a < 16; a++) o[a] = c[a];
    }
    
    function crypto_scalarmult(q, n, p) {
      var z = new Uint8Array(32);
      var x = new Float64Array(80), r, i;
      var a = gf(), b = gf(), c = gf(),
          d = gf(), e = gf(), f = gf();
      for (i = 0; i < 31; i++) z[i] = n[i];
      z[31]=(n[31]&127)|64;
      z[0]&=248;
      unpack25519(x,p);
      for (i = 0; i < 16; i++) {
        b[i]=x[i];
        d[i]=a[i]=c[i]=0;
      }
      a[0]=d[0]=1;
      for (i=254; i>=0; --i) {
        r=(z[i>>>3]>>>(i&7))&1;
        sel25519(a,b,r);
        sel25519(c,d,r);
        A(e,a,c);
        Z(a,a,c);
        A(c,b,d);
        Z(b,b,d);
        S(d,e);
        S(f,a);
        M(a,c,a);
        M(c,b,e);
        A(e,a,c);
        Z(a,a,c);
        S(b,a);
        Z(c,d,f);
        M(a,c,_121665);
        A(a,a,d);
        M(c,c,a);
        M(a,d,f);
        M(d,b,x);
        S(b,e);
        sel25519(a,b,r);
        sel25519(c,d,r);
      }
      for (i = 0; i < 16; i++) {
        x[i+16]=a[i];
        x[i+32]=c[i];
        x[i+48]=b[i];
        x[i+64]=d[i];
      }
      var x32 = x.subarray(32);
      var x16 = x.subarray(16);
      inv25519(x32,x32);
      M(x16,x16,x32);
      pack25519(q,x16);
      return 0;
    }
    
    function crypto_scalarmult_base(q, n) {
      return crypto_scalarmult(q, n, _9);
    }
    
    function crypto_box_keypair(y, x) {
      randombytes(x, 32);
      return crypto_scalarmult_base(y, x);
    }
    
    function crypto_box_beforenm(k, y, x) {
      var s = new Uint8Array(32);
      crypto_scalarmult(s, x, y);
      return crypto_core_hsalsa20(k, _0, s, sigma);
    }
    
    var crypto_box_afternm = crypto_secretbox;
    var crypto_box_open_afternm = crypto_secretbox_open;
    
    function crypto_box(c, m, d, n, y, x) {
      var k = new Uint8Array(32);
      crypto_box_beforenm(k, y, x);
      return crypto_box_afternm(c, m, d, n, k);
    }
    
    function crypto_box_open(m, c, d, n, y, x) {
      var k = new Uint8Array(32);
      crypto_box_beforenm(k, y, x);
      return crypto_box_open_afternm(m, c, d, n, k);
    }
    
    var K = [
      0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
      0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
      0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
      0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
      0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
      0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
      0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
      0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
      0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
      0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
      0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
      0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
      0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
      0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
      0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
      0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
      0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
      0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
      0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
      0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
      0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
      0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
      0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
      0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
      0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
      0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
      0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
      0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
      0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
      0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
      0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
      0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
      0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
      0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
      0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
      0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
      0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
      0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
      0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
      0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
    ];
    
    function crypto_hashblocks_hl(hh, hl, m, n) {
      var wh = new Int32Array(16), wl = new Int32Array(16),
          bh0, bh1, bh2, bh3, bh4, bh5, bh6, bh7,
          bl0, bl1, bl2, bl3, bl4, bl5, bl6, bl7,
          th, tl, i, j, h, l, a, b, c, d;
    
      var ah0 = hh[0],
          ah1 = hh[1],
          ah2 = hh[2],
          ah3 = hh[3],
          ah4 = hh[4],
          ah5 = hh[5],
          ah6 = hh[6],
          ah7 = hh[7],
    
          al0 = hl[0],
          al1 = hl[1],
          al2 = hl[2],
          al3 = hl[3],
          al4 = hl[4],
          al5 = hl[5],
          al6 = hl[6],
          al7 = hl[7];
    
      var pos = 0;
      while (n >= 128) {
        for (i = 0; i < 16; i++) {
          j = 8 * i + pos;
          wh[i] = (m[j+0] << 24) | (m[j+1] << 16) | (m[j+2] << 8) | m[j+3];
          wl[i] = (m[j+4] << 24) | (m[j+5] << 16) | (m[j+6] << 8) | m[j+7];
        }
        for (i = 0; i < 80; i++) {
          bh0 = ah0;
          bh1 = ah1;
          bh2 = ah2;
          bh3 = ah3;
          bh4 = ah4;
          bh5 = ah5;
          bh6 = ah6;
          bh7 = ah7;
    
          bl0 = al0;
          bl1 = al1;
          bl2 = al2;
          bl3 = al3;
          bl4 = al4;
          bl5 = al5;
          bl6 = al6;
          bl7 = al7;
    
          // add
          h = ah7;
          l = al7;
    
          a = l & 0xffff; b = l >>> 16;
          c = h & 0xffff; d = h >>> 16;
    
          // Sigma1
          h = ((ah4 >>> 14) | (al4 << (32-14))) ^ ((ah4 >>> 18) | (al4 << (32-18))) ^ ((al4 >>> (41-32)) | (ah4 << (32-(41-32))));
          l = ((al4 >>> 14) | (ah4 << (32-14))) ^ ((al4 >>> 18) | (ah4 << (32-18))) ^ ((ah4 >>> (41-32)) | (al4 << (32-(41-32))));
    
          a += l & 0xffff; b += l >>> 16;
          c += h & 0xffff; d += h >>> 16;
    
          // Ch
          h = (ah4 & ah5) ^ (~ah4 & ah6);
          l = (al4 & al5) ^ (~al4 & al6);
    
          a += l & 0xffff; b += l >>> 16;
          c += h & 0xffff; d += h >>> 16;
    
          // K
          h = K[i*2];
          l = K[i*2+1];
    
          a += l & 0xffff; b += l >>> 16;
          c += h & 0xffff; d += h >>> 16;
    
          // w
          h = wh[i%16];
          l = wl[i%16];
    
          a += l & 0xffff; b += l >>> 16;
          c += h & 0xffff; d += h >>> 16;
    
          b += a >>> 16;
          c += b >>> 16;
          d += c >>> 16;
    
          th = c & 0xffff | d << 16;
          tl = a & 0xffff | b << 16;
    
          // add
          h = th;
          l = tl;
    
          a = l & 0xffff; b = l >>> 16;
          c = h & 0xffff; d = h >>> 16;
    
          // Sigma0
          h = ((ah0 >>> 28) | (al0 << (32-28))) ^ ((al0 >>> (34-32)) | (ah0 << (32-(34-32)))) ^ ((al0 >>> (39-32)) | (ah0 << (32-(39-32))));
          l = ((al0 >>> 28) | (ah0 << (32-28))) ^ ((ah0 >>> (34-32)) | (al0 << (32-(34-32)))) ^ ((ah0 >>> (39-32)) | (al0 << (32-(39-32))));
    
          a += l & 0xffff; b += l >>> 16;
          c += h & 0xffff; d += h >>> 16;
    
          // Maj
          h = (ah0 & ah1) ^ (ah0 & ah2) ^ (ah1 & ah2);
          l = (al0 & al1) ^ (al0 & al2) ^ (al1 & al2);
    
          a += l & 0xffff; b += l >>> 16;
          c += h & 0xffff; d += h >>> 16;
    
          b += a >>> 16;
          c += b >>> 16;
          d += c >>> 16;
    
          bh7 = (c & 0xffff) | (d << 16);
          bl7 = (a & 0xffff) | (b << 16);
    
          // add
          h = bh3;
          l = bl3;
    
          a = l & 0xffff; b = l >>> 16;
          c = h & 0xffff; d = h >>> 16;
    
          h = th;
          l = tl;
    
          a += l & 0xffff; b += l >>> 16;
          c += h & 0xffff; d += h >>> 16;
    
          b += a >>> 16;
          c += b >>> 16;
          d += c >>> 16;
    
          bh3 = (c & 0xffff) | (d << 16);
          bl3 = (a & 0xffff) | (b << 16);
    
          ah1 = bh0;
          ah2 = bh1;
          ah3 = bh2;
          ah4 = bh3;
          ah5 = bh4;
          ah6 = bh5;
          ah7 = bh6;
          ah0 = bh7;
    
          al1 = bl0;
          al2 = bl1;
          al3 = bl2;
          al4 = bl3;
          al5 = bl4;
          al6 = bl5;
          al7 = bl6;
          al0 = bl7;
    
          if (i%16 === 15) {
            for (j = 0; j < 16; j++) {
              // add
              h = wh[j];
              l = wl[j];
    
              a = l & 0xffff; b = l >>> 16;
              c = h & 0xffff; d = h >>> 16;
    
              h = wh[(j+9)%16];
              l = wl[(j+9)%16];
    
              a += l & 0xffff; b += l >>> 16;
              c += h & 0xffff; d += h >>> 16;
    
              // sigma0
              th = wh[(j+1)%16];
              tl = wl[(j+1)%16];
              h = ((th >>> 1) | (tl << (32-1))) ^ ((th >>> 8) | (tl << (32-8))) ^ (th >>> 7);
              l = ((tl >>> 1) | (th << (32-1))) ^ ((tl >>> 8) | (th << (32-8))) ^ ((tl >>> 7) | (th << (32-7)));
    
              a += l & 0xffff; b += l >>> 16;
              c += h & 0xffff; d += h >>> 16;
    
              // sigma1
              th = wh[(j+14)%16];
              tl = wl[(j+14)%16];
              h = ((th >>> 19) | (tl << (32-19))) ^ ((tl >>> (61-32)) | (th << (32-(61-32)))) ^ (th >>> 6);
              l = ((tl >>> 19) | (th << (32-19))) ^ ((th >>> (61-32)) | (tl << (32-(61-32)))) ^ ((tl >>> 6) | (th << (32-6)));
    
              a += l & 0xffff; b += l >>> 16;
              c += h & 0xffff; d += h >>> 16;
    
              b += a >>> 16;
              c += b >>> 16;
              d += c >>> 16;
    
              wh[j] = (c & 0xffff) | (d << 16);
              wl[j] = (a & 0xffff) | (b << 16);
            }
          }
        }
    
        // add
        h = ah0;
        l = al0;
    
        a = l & 0xffff; b = l >>> 16;
        c = h & 0xffff; d = h >>> 16;
    
        h = hh[0];
        l = hl[0];
    
        a += l & 0xffff; b += l >>> 16;
        c += h & 0xffff; d += h >>> 16;
    
        b += a >>> 16;
        c += b >>> 16;
        d += c >>> 16;
    
        hh[0] = ah0 = (c & 0xffff) | (d << 16);
        hl[0] = al0 = (a & 0xffff) | (b << 16);
    
        h = ah1;
        l = al1;
    
        a = l & 0xffff; b = l >>> 16;
        c = h & 0xffff; d = h >>> 16;
    
        h = hh[1];
        l = hl[1];
    
        a += l & 0xffff; b += l >>> 16;
        c += h & 0xffff; d += h >>> 16;
    
        b += a >>> 16;
        c += b >>> 16;
        d += c >>> 16;
    
        hh[1] = ah1 = (c & 0xffff) | (d << 16);
        hl[1] = al1 = (a & 0xffff) | (b << 16);
    
        h = ah2;
        l = al2;
    
        a = l & 0xffff; b = l >>> 16;
        c = h & 0xffff; d = h >>> 16;
    
        h = hh[2];
        l = hl[2];
    
        a += l & 0xffff; b += l >>> 16;
        c += h & 0xffff; d += h >>> 16;
    
        b += a >>> 16;
        c += b >>> 16;
        d += c >>> 16;
    
        hh[2] = ah2 = (c & 0xffff) | (d << 16);
        hl[2] = al2 = (a & 0xffff) | (b << 16);
    
        h = ah3;
        l = al3;
    
        a = l & 0xffff; b = l >>> 16;
        c = h & 0xffff; d = h >>> 16;
    
        h = hh[3];
        l = hl[3];
    
        a += l & 0xffff; b += l >>> 16;
        c += h & 0xffff; d += h >>> 16;
    
        b += a >>> 16;
        c += b >>> 16;
        d += c >>> 16;
    
        hh[3] = ah3 = (c & 0xffff) | (d << 16);
        hl[3] = al3 = (a & 0xffff) | (b << 16);
    
        h = ah4;
        l = al4;
    
        a = l & 0xffff; b = l >>> 16;
        c = h & 0xffff; d = h >>> 16;
    
        h = hh[4];
        l = hl[4];
    
        a += l & 0xffff; b += l >>> 16;
        c += h & 0xffff; d += h >>> 16;
    
        b += a >>> 16;
        c += b >>> 16;
        d += c >>> 16;
    
        hh[4] = ah4 = (c & 0xffff) | (d << 16);
        hl[4] = al4 = (a & 0xffff) | (b << 16);
    
        h = ah5;
        l = al5;
    
        a = l & 0xffff; b = l >>> 16;
        c = h & 0xffff; d = h >>> 16;
    
        h = hh[5];
        l = hl[5];
    
        a += l & 0xffff; b += l >>> 16;
        c += h & 0xffff; d += h >>> 16;
    
        b += a >>> 16;
        c += b >>> 16;
        d += c >>> 16;
    
        hh[5] = ah5 = (c & 0xffff) | (d << 16);
        hl[5] = al5 = (a & 0xffff) | (b << 16);
    
        h = ah6;
        l = al6;
    
        a = l & 0xffff; b = l >>> 16;
        c = h & 0xffff; d = h >>> 16;
    
        h = hh[6];
        l = hl[6];
    
        a += l & 0xffff; b += l >>> 16;
        c += h & 0xffff; d += h >>> 16;
    
        b += a >>> 16;
        c += b >>> 16;
        d += c >>> 16;
    
        hh[6] = ah6 = (c & 0xffff) | (d << 16);
        hl[6] = al6 = (a & 0xffff) | (b << 16);
    
        h = ah7;
        l = al7;
    
        a = l & 0xffff; b = l >>> 16;
        c = h & 0xffff; d = h >>> 16;
    
        h = hh[7];
        l = hl[7];
    
        a += l & 0xffff; b += l >>> 16;
        c += h & 0xffff; d += h >>> 16;
    
        b += a >>> 16;
        c += b >>> 16;
        d += c >>> 16;
    
        hh[7] = ah7 = (c & 0xffff) | (d << 16);
        hl[7] = al7 = (a & 0xffff) | (b << 16);
    
        pos += 128;
        n -= 128;
      }
    
      return n;
    }
    
    function crypto_hash(out, m, n) {
      var hh = new Int32Array(8),
          hl = new Int32Array(8),
          x = new Uint8Array(256),
          i, b = n;
    
      hh[0] = 0x6a09e667;
      hh[1] = 0xbb67ae85;
      hh[2] = 0x3c6ef372;
      hh[3] = 0xa54ff53a;
      hh[4] = 0x510e527f;
      hh[5] = 0x9b05688c;
      hh[6] = 0x1f83d9ab;
      hh[7] = 0x5be0cd19;
    
      hl[0] = 0xf3bcc908;
      hl[1] = 0x84caa73b;
      hl[2] = 0xfe94f82b;
      hl[3] = 0x5f1d36f1;
      hl[4] = 0xade682d1;
      hl[5] = 0x2b3e6c1f;
      hl[6] = 0xfb41bd6b;
      hl[7] = 0x137e2179;
    
      crypto_hashblocks_hl(hh, hl, m, n);
      n %= 128;
    
      for (i = 0; i < n; i++) x[i] = m[b-n+i];
      x[n] = 128;
    
      n = 256-128*(n<112?1:0);
      x[n-9] = 0;
      ts64(x, n-8,  (b / 0x20000000) | 0, b << 3);
      crypto_hashblocks_hl(hh, hl, x, n);
    
      for (i = 0; i < 8; i++) ts64(out, 8*i, hh[i], hl[i]);
    
      return 0;
    }
    
    function add(p, q) {
      var a = gf(), b = gf(), c = gf(),
          d = gf(), e = gf(), f = gf(),
          g = gf(), h = gf(), t = gf();
    
      Z(a, p[1], p[0]);
      Z(t, q[1], q[0]);
      M(a, a, t);
      A(b, p[0], p[1]);
      A(t, q[0], q[1]);
      M(b, b, t);
      M(c, p[3], q[3]);
      M(c, c, D2);
      M(d, p[2], q[2]);
      A(d, d, d);
      Z(e, b, a);
      Z(f, d, c);
      A(g, d, c);
      A(h, b, a);
    
      M(p[0], e, f);
      M(p[1], h, g);
      M(p[2], g, f);
      M(p[3], e, h);
    }
    
    function cswap(p, q, b) {
      var i;
      for (i = 0; i < 4; i++) {
        sel25519(p[i], q[i], b);
      }
    }
    
    function pack(r, p) {
      var tx = gf(), ty = gf(), zi = gf();
      inv25519(zi, p[2]);
      M(tx, p[0], zi);
      M(ty, p[1], zi);
      pack25519(r, ty);
      r[31] ^= par25519(tx) << 7;
    }
    
    function scalarmult(p, q, s) {
      var b, i;
      set25519(p[0], gf0);
      set25519(p[1], gf1);
      set25519(p[2], gf1);
      set25519(p[3], gf0);
      for (i = 255; i >= 0; --i) {
        b = (s[(i/8)|0] >> (i&7)) & 1;
        cswap(p, q, b);
        add(q, p);
        add(p, p);
        cswap(p, q, b);
      }
    }
    
    function scalarbase(p, s) {
      var q = [gf(), gf(), gf(), gf()];
      set25519(q[0], X);
      set25519(q[1], Y);
      set25519(q[2], gf1);
      M(q[3], X, Y);
      scalarmult(p, q, s);
    }
    
    function crypto_sign_keypair(pk, sk, seeded) {
      var d = new Uint8Array(64);
      var p = [gf(), gf(), gf(), gf()];
      var i;
    
      if (!seeded) randombytes(sk, 32);
      crypto_hash(d, sk, 32);
      d[0] &= 248;
      d[31] &= 127;
      d[31] |= 64;
    
      scalarbase(p, d);
      pack(pk, p);
    
      for (i = 0; i < 32; i++) sk[i+32] = pk[i];
      return 0;
    }
    
    var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]);
    
    function modL(r, x) {
      var carry, i, j, k;
      for (i = 63; i >= 32; --i) {
        carry = 0;
        for (j = i - 32, k = i - 12; j < k; ++j) {
          x[j] += carry - 16 * x[i] * L[j - (i - 32)];
          carry = (x[j] + 128) >> 8;
          x[j] -= carry * 256;
        }
        x[j] += carry;
        x[i] = 0;
      }
      carry = 0;
      for (j = 0; j < 32; j++) {
        x[j] += carry - (x[31] >> 4) * L[j];
        carry = x[j] >> 8;
        x[j] &= 255;
      }
      for (j = 0; j < 32; j++) x[j] -= carry * L[j];
      for (i = 0; i < 32; i++) {
        x[i+1] += x[i] >> 8;
        r[i] = x[i] & 255;
      }
    }
    
    function reduce(r) {
      var x = new Float64Array(64), i;
      for (i = 0; i < 64; i++) x[i] = r[i];
      for (i = 0; i < 64; i++) r[i] = 0;
      modL(r, x);
    }
    
    // Note: difference from C - smlen returned, not passed as argument.
    function crypto_sign(sm, m, n, sk) {
      var d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64);
      var i, j, x = new Float64Array(64);
      var p = [gf(), gf(), gf(), gf()];
    
      crypto_hash(d, sk, 32);
      d[0] &= 248;
      d[31] &= 127;
      d[31] |= 64;
    
      var smlen = n + 64;
      for (i = 0; i < n; i++) sm[64 + i] = m[i];
      for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i];
    
      crypto_hash(r, sm.subarray(32), n+32);
      reduce(r);
      scalarbase(p, r);
      pack(sm, p);
    
      for (i = 32; i < 64; i++) sm[i] = sk[i];
      crypto_hash(h, sm, n + 64);
      reduce(h);
    
      for (i = 0; i < 64; i++) x[i] = 0;
      for (i = 0; i < 32; i++) x[i] = r[i];
      for (i = 0; i < 32; i++) {
        for (j = 0; j < 32; j++) {
          x[i+j] += h[i] * d[j];
        }
      }
    
      modL(sm.subarray(32), x);
      return smlen;
    }
    
    function unpackneg(r, p) {
      var t = gf(), chk = gf(), num = gf(),
          den = gf(), den2 = gf(), den4 = gf(),
          den6 = gf();
    
      set25519(r[2], gf1);
      unpack25519(r[1], p);
      S(num, r[1]);
      M(den, num, D);
      Z(num, num, r[2]);
      A(den, r[2], den);
    
      S(den2, den);
      S(den4, den2);
      M(den6, den4, den2);
      M(t, den6, num);
      M(t, t, den);
    
      pow2523(t, t);
      M(t, t, num);
      M(t, t, den);
      M(t, t, den);
      M(r[0], t, den);
    
      S(chk, r[0]);
      M(chk, chk, den);
      if (neq25519(chk, num)) M(r[0], r[0], I);
    
      S(chk, r[0]);
      M(chk, chk, den);
      if (neq25519(chk, num)) return -1;
    
      if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]);
    
      M(r[3], r[0], r[1]);
      return 0;
    }
    
    function crypto_sign_open(m, sm, n, pk) {
      var i, mlen;
      var t = new Uint8Array(32), h = new Uint8Array(64);
      var p = [gf(), gf(), gf(), gf()],
          q = [gf(), gf(), gf(), gf()];
    
      mlen = -1;
      if (n < 64) return -1;
    
      if (unpackneg(q, pk)) return -1;
    
      for (i = 0; i < n; i++) m[i] = sm[i];
      for (i = 0; i < 32; i++) m[i+32] = pk[i];
      crypto_hash(h, m, n);
      reduce(h);
      scalarmult(p, q, h);
    
      scalarbase(q, sm.subarray(32));
      add(p, q);
      pack(t, p);
    
      n -= 64;
      if (crypto_verify_32(sm, 0, t, 0)) {
        for (i = 0; i < n; i++) m[i] = 0;
        return -1;
      }
    
      for (i = 0; i < n; i++) m[i] = sm[i + 64];
      mlen = n;
      return mlen;
    }
    
    var crypto_secretbox_KEYBYTES = 32,
        crypto_secretbox_NONCEBYTES = 24,
        crypto_secretbox_ZEROBYTES = 32,
        crypto_secretbox_BOXZEROBYTES = 16,
        crypto_scalarmult_BYTES = 32,
        crypto_scalarmult_SCALARBYTES = 32,
        crypto_box_PUBLICKEYBYTES = 32,
        crypto_box_SECRETKEYBYTES = 32,
        crypto_box_BEFORENMBYTES = 32,
        crypto_box_NONCEBYTES = crypto_secretbox_NONCEBYTES,
        crypto_box_ZEROBYTES = crypto_secretbox_ZEROBYTES,
        crypto_box_BOXZEROBYTES = crypto_secretbox_BOXZEROBYTES,
        crypto_sign_BYTES = 64,
        crypto_sign_PUBLICKEYBYTES = 32,
        crypto_sign_SECRETKEYBYTES = 64,
        crypto_sign_SEEDBYTES = 32,
        crypto_hash_BYTES = 64;
    
    nacl.lowlevel = {
      crypto_core_hsalsa20: crypto_core_hsalsa20,
      crypto_stream_xor: crypto_stream_xor,
      crypto_stream: crypto_stream,
      crypto_stream_salsa20_xor: crypto_stream_salsa20_xor,
      crypto_stream_salsa20: crypto_stream_salsa20,
      crypto_onetimeauth: crypto_onetimeauth,
      crypto_onetimeauth_verify: crypto_onetimeauth_verify,
      crypto_verify_16: crypto_verify_16,
      crypto_verify_32: crypto_verify_32,
      crypto_secretbox: crypto_secretbox,
      crypto_secretbox_open: crypto_secretbox_open,
      crypto_scalarmult: crypto_scalarmult,
      crypto_scalarmult_base: crypto_scalarmult_base,
      crypto_box_beforenm: crypto_box_beforenm,
      crypto_box_afternm: crypto_box_afternm,
      crypto_box: crypto_box,
      crypto_box_open: crypto_box_open,
      crypto_box_keypair: crypto_box_keypair,
      crypto_hash: crypto_hash,
      crypto_sign: crypto_sign,
      crypto_sign_keypair: crypto_sign_keypair,
      crypto_sign_open: crypto_sign_open,
    
      crypto_secretbox_KEYBYTES: crypto_secretbox_KEYBYTES,
      crypto_secretbox_NONCEBYTES: crypto_secretbox_NONCEBYTES,
      crypto_secretbox_ZEROBYTES: crypto_secretbox_ZEROBYTES,
      crypto_secretbox_BOXZEROBYTES: crypto_secretbox_BOXZEROBYTES,
      crypto_scalarmult_BYTES: crypto_scalarmult_BYTES,
      crypto_scalarmult_SCALARBYTES: crypto_scalarmult_SCALARBYTES,
      crypto_box_PUBLICKEYBYTES: crypto_box_PUBLICKEYBYTES,
      crypto_box_SECRETKEYBYTES: crypto_box_SECRETKEYBYTES,
      crypto_box_BEFORENMBYTES: crypto_box_BEFORENMBYTES,
      crypto_box_NONCEBYTES: crypto_box_NONCEBYTES,
      crypto_box_ZEROBYTES: crypto_box_ZEROBYTES,
      crypto_box_BOXZEROBYTES: crypto_box_BOXZEROBYTES,
      crypto_sign_BYTES: crypto_sign_BYTES,
      crypto_sign_PUBLICKEYBYTES: crypto_sign_PUBLICKEYBYTES,
      crypto_sign_SECRETKEYBYTES: crypto_sign_SECRETKEYBYTES,
      crypto_sign_SEEDBYTES: crypto_sign_SEEDBYTES,
      crypto_hash_BYTES: crypto_hash_BYTES
    };
    
    /* High-level API */
    
    function checkLengths(k, n) {
      if (k.length !== crypto_secretbox_KEYBYTES) throw new Error('bad key size');
      if (n.length !== crypto_secretbox_NONCEBYTES) throw new Error('bad nonce size');
    }
    
    function checkBoxLengths(pk, sk) {
      if (pk.length !== crypto_box_PUBLICKEYBYTES) throw new Error('bad public key size');
      if (sk.length !== crypto_box_SECRETKEYBYTES) throw new Error('bad secret key size');
    }
    
    function checkArrayTypes() {
      var t, i;
      for (i = 0; i < arguments.length; i++) {
         if ((t = Object.prototype.toString.call(arguments[i])) !== '[object Uint8Array]')
           throw new TypeError('unexpected type ' + t + ', use Uint8Array');
      }
    }
    
    function cleanup(arr) {
      for (var i = 0; i < arr.length; i++) arr[i] = 0;
    }
    
    nacl.util = {};
    
    nacl.util.decodeUTF8 = function(s) {
      var i, d = unescape(encodeURIComponent(s)), b = new Uint8Array(d.length);
      for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
      return b;
    };
    
    nacl.util.encodeUTF8 = function(arr) {
      var i, s = [];
      for (i = 0; i < arr.length; i++) s.push(String.fromCharCode(arr[i]));
      return decodeURIComponent(escape(s.join('')));
    };
    
    nacl.util.encodeBase64 = function(arr) {
      if (typeof btoa === 'undefined') {
        return (new Buffer(arr)).toString('base64');
      } else {
        var i, s = [], len = arr.length;
        for (i = 0; i < len; i++) s.push(String.fromCharCode(arr[i]));
        return btoa(s.join(''));
      }
    };
    
    nacl.util.decodeBase64 = function(s) {
      if (typeof atob === 'undefined') {
        return new Uint8Array(Array.prototype.slice.call(new Buffer(s, 'base64'), 0));
      } else {
        var i, d = atob(s), b = new Uint8Array(d.length);
        for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
        return b;
      }
    };
    
    nacl.randomBytes = function(n) {
      var b = new Uint8Array(n);
      randombytes(b, n);
      return b;
    };
    
    nacl.secretbox = function(msg, nonce, key) {
      checkArrayTypes(msg, nonce, key);
      checkLengths(key, nonce);
      var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length);
      var c = new Uint8Array(m.length);
      for (var i = 0; i < msg.length; i++) m[i+crypto_secretbox_ZEROBYTES] = msg[i];
      crypto_secretbox(c, m, m.length, nonce, key);
      return c.subarray(crypto_secretbox_BOXZEROBYTES);
    };
    
    nacl.secretbox.open = function(box, nonce, key) {
      checkArrayTypes(box, nonce, key);
      checkLengths(key, nonce);
      var c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length);
      var m = new Uint8Array(c.length);
      for (var i = 0; i < box.length; i++) c[i+crypto_secretbox_BOXZEROBYTES] = box[i];
      if (c.length < 32) return false;
      if (crypto_secretbox_open(m, c, c.length, nonce, key) !== 0) return false;
      return m.subarray(crypto_secretbox_ZEROBYTES);
    };
    
    nacl.secretbox.keyLength = crypto_secretbox_KEYBYTES;
    nacl.secretbox.nonceLength = crypto_secretbox_NONCEBYTES;
    nacl.secretbox.overheadLength = crypto_secretbox_BOXZEROBYTES;
    
    nacl.scalarMult = function(n, p) {
      checkArrayTypes(n, p);
      if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size');
      if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size');
      var q = new Uint8Array(crypto_scalarmult_BYTES);
      crypto_scalarmult(q, n, p);
      return q;
    };
    
    nacl.scalarMult.base = function(n) {
      checkArrayTypes(n);
      if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size');
      var q = new Uint8Array(crypto_scalarmult_BYTES);
      crypto_scalarmult_base(q, n);
      return q;
    };
    
    nacl.scalarMult.scalarLength = crypto_scalarmult_SCALARBYTES;
    nacl.scalarMult.groupElementLength = crypto_scalarmult_BYTES;
    
    nacl.box = function(msg, nonce, publicKey, secretKey) {
      var k = nacl.box.before(publicKey, secretKey);
      return nacl.secretbox(msg, nonce, k);
    };
    
    nacl.box.before = function(publicKey, secretKey) {
      checkArrayTypes(publicKey, secretKey);
      checkBoxLengths(publicKey, secretKey);
      var k = new Uint8Array(crypto_box_BEFORENMBYTES);
      crypto_box_beforenm(k, publicKey, secretKey);
      return k;
    };
    
    nacl.box.after = nacl.secretbox;
    
    nacl.box.open = function(msg, nonce, publicKey, secretKey) {
      var k = nacl.box.before(publicKey, secretKey);
      return nacl.secretbox.open(msg, nonce, k);
    };
    
    nacl.box.open.after = nacl.secretbox.open;
    
    nacl.box.keyPair = function() {
      var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES);
      var sk = new Uint8Array(crypto_box_SECRETKEYBYTES);
      crypto_box_keypair(pk, sk);
      return {publicKey: pk, secretKey: sk};
    };
    
    nacl.box.keyPair.fromSecretKey = function(secretKey) {
      checkArrayTypes(secretKey);
      if (secretKey.length !== crypto_box_SECRETKEYBYTES)
        throw new Error('bad secret key size');
      var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES);
      crypto_scalarmult_base(pk, secretKey);
      return {publicKey: pk, secretKey: new Uint8Array(secretKey)};
    };
    
    nacl.box.publicKeyLength = crypto_box_PUBLICKEYBYTES;
    nacl.box.secretKeyLength = crypto_box_SECRETKEYBYTES;
    nacl.box.sharedKeyLength = crypto_box_BEFORENMBYTES;
    nacl.box.nonceLength = crypto_box_NONCEBYTES;
    nacl.box.overheadLength = nacl.secretbox.overheadLength;
    
    nacl.sign = function(msg, secretKey) {
      checkArrayTypes(msg, secretKey);
      if (secretKey.length !== crypto_sign_SECRETKEYBYTES)
        throw new Error('bad secret key size');
      var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length);
      crypto_sign(signedMsg, msg, msg.length, secretKey);
      return signedMsg;
    };
    
    nacl.sign.open = function(signedMsg, publicKey) {
      if (arguments.length !== 2)
        throw new Error('nacl.sign.open accepts 2 arguments; did you mean to use nacl.sign.detached.verify?');
      checkArrayTypes(signedMsg, publicKey);
      if (publicKey.length !== crypto_sign_PUBLICKEYBYTES)
        throw new Error('bad public key size');
      var tmp = new Uint8Array(signedMsg.length);
      var mlen = crypto_sign_open(tmp, signedMsg, signedMsg.length, publicKey);
      if (mlen < 0) return null;
      var m = new Uint8Array(mlen);
      for (var i = 0; i < m.length; i++) m[i] = tmp[i];
      return m;
    };
    
    nacl.sign.detached = function(msg, secretKey) {
      var signedMsg = nacl.sign(msg, secretKey);
      var sig = new Uint8Array(crypto_sign_BYTES);
      for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i];
      return sig;
    };
    
    nacl.sign.detached.verify = function(msg, sig, publicKey) {
      checkArrayTypes(msg, sig, publicKey);
      if (sig.length !== crypto_sign_BYTES)
        throw new Error('bad signature size');
      if (publicKey.length !== crypto_sign_PUBLICKEYBYTES)
        throw new Error('bad public key size');
      var sm = new Uint8Array(crypto_sign_BYTES + msg.length);
      var m = new Uint8Array(crypto_sign_BYTES + msg.length);
      var i;
      for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i];
      for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i];
      return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0);
    };
    
    nacl.sign.keyPair = function() {
      var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES);
      var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES);
      crypto_sign_keypair(pk, sk);
      return {publicKey: pk, secretKey: sk};
    };
    
    nacl.sign.keyPair.fromSecretKey = function(secretKey) {
      checkArrayTypes(secretKey);
      if (secretKey.length !== crypto_sign_SECRETKEYBYTES)
        throw new Error('bad secret key size');
      var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES);
      for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i];
      return {publicKey: pk, secretKey: new Uint8Array(secretKey)};
    };
    
    nacl.sign.keyPair.fromSeed = function(seed) {
      checkArrayTypes(seed);
      if (seed.length !== crypto_sign_SEEDBYTES)
        throw new Error('bad seed size');
      var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES);
      var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES);
      for (var i = 0; i < 32; i++) sk[i] = seed[i];
      crypto_sign_keypair(pk, sk, true);
      return {publicKey: pk, secretKey: sk};
    };
    
    nacl.sign.publicKeyLength = crypto_sign_PUBLICKEYBYTES;
    nacl.sign.secretKeyLength = crypto_sign_SECRETKEYBYTES;
    nacl.sign.seedLength = crypto_sign_SEEDBYTES;
    nacl.sign.signatureLength = crypto_sign_BYTES;
    
    nacl.hash = function(msg) {
      checkArrayTypes(msg);
      var h = new Uint8Array(crypto_hash_BYTES);
      crypto_hash(h, msg, msg.length);
      return h;
    };
    
    nacl.hash.hashLength = crypto_hash_BYTES;
    
    nacl.verify = function(x, y) {
      checkArrayTypes(x, y);
      // Zero length arguments are considered not equal.
      if (x.length === 0 || y.length === 0) return false;
      if (x.length !== y.length) return false;
      return (vn(x, 0, y, 0, x.length) === 0) ? true : false;
    };
    
    nacl.setPRNG = function(fn) {
      randombytes = fn;
    };
    
    (function() {
      // Initialize PRNG if environment provides CSPRNG.
      // If not, methods calling randombytes will throw.
      var crypto;
      if (typeof window !== 'undefined') {
        // Browser.
        if (window.crypto && window.crypto.getRandomValues) {
          crypto = window.crypto; // Standard
        } else if (window.msCrypto && window.msCrypto.getRandomValues) {
          crypto = window.msCrypto; // Internet Explorer 11+
        }
        if (crypto) {
          nacl.setPRNG(function(x, n) {
            var i, v = new Uint8Array(n);
            crypto.getRandomValues(v);
            for (i = 0; i < n; i++) x[i] = v[i];
            cleanup(v);
          });
        }
      } else if (typeof require !== 'undefined') {
        // Node.js.
        crypto = require('crypto');
        if (crypto) {
          nacl.setPRNG(function(x, n) {
            var i, v = crypto.randomBytes(n);
            for (i = 0; i < n; i++) x[i] = v[i];
            cleanup(v);
          });
        }
      }
    })();
    
    })(typeof module !== 'undefined' && module.exports ? module.exports : (window.nacl = window.nacl || {}));
    "Generated from Java with JSweet 1.0.0 - http://www.jsweet.org";
    var RIPEMD160 = (function () {
        function RIPEMD160() {
            this.MDbuf = [];
            this.MDbuf[0] = 1732584193;
            this.MDbuf[1] = -271733879;
            this.MDbuf[2] = -1732584194;
            this.MDbuf[3] = 271733878;
            this.MDbuf[4] = -1009589776;
    		this.working = new Int32Array(16);
    		
            this.working_ptr = 0;
            this.msglen = 0;
        }
        RIPEMD160.prototype.reset = function () {
            this.MDbuf = [];
            this.MDbuf[0] = 1732584193;
            this.MDbuf[1] = -271733879;
            this.MDbuf[2] = -1732584194;
            this.MDbuf[3] = 271733878;
            this.MDbuf[4] = -1009589776;
            this.working = new Int32Array(16);
            this.working_ptr = 0;
            this.msglen = 0;
        };
        RIPEMD160.prototype.compress = function (X) {
            var index = 0;
            var a;
            var b;
            var c;
            var d;
            var e;
            var A;
            var B;
            var C;
            var D;
            var E;
            var temp;
            var s;
            A = a = this.MDbuf[0];
            B = b = this.MDbuf[1];
            C = c = this.MDbuf[2];
            D = d = this.MDbuf[3];
            E = e = this.MDbuf[4];
            for (; index < 16; index++) {
                temp = a + (b ^ c ^ d) + X[RIPEMD160.IndexArray[0][index]];
                a = e;
                e = d;
                d = (c << 10) | (c >>> 22);
                c = b;
                s = RIPEMD160.ArgArray[0][index];
                b = ((temp << s) | (temp >>> (32 - s))) + a;
                temp = A + (B ^ (C | ~D)) + X[RIPEMD160.IndexArray[1][index]] + 1352829926;
                A = E;
                E = D;
                D = (C << 10) | (C >>> 22);
                C = B;
                s = RIPEMD160.ArgArray[1][index];
                B = ((temp << s) | (temp >>> (32 - s))) + A;
            }
            for (; index < 32; index++) {
                temp = a + ((b & c) | (~b & d)) + X[RIPEMD160.IndexArray[0][index]] + 1518500249;
                a = e;
                e = d;
                d = (c << 10) | (c >>> 22);
                c = b;
                s = RIPEMD160.ArgArray[0][index];
                b = ((temp << s) | (temp >>> (32 - s))) + a;
                temp = A + ((B & D) | (C & ~D)) + X[RIPEMD160.IndexArray[1][index]] + 1548603684;
                A = E;
                E = D;
                D = (C << 10) | (C >>> 22);
                C = B;
                s = RIPEMD160.ArgArray[1][index];
                B = ((temp << s) | (temp >>> (32 - s))) + A;
            }
            for (; index < 48; index++) {
                temp = a + ((b | ~c) ^ d) + X[RIPEMD160.IndexArray[0][index]] + 1859775393;
                a = e;
                e = d;
                d = (c << 10) | (c >>> 22);
                c = b;
                s = RIPEMD160.ArgArray[0][index];
                b = ((temp << s) | (temp >>> (32 - s))) + a;
                temp = A + ((B | ~C) ^ D) + X[RIPEMD160.IndexArray[1][index]] + 1836072691;
                A = E;
                E = D;
                D = (C << 10) | (C >>> 22);
                C = B;
                s = RIPEMD160.ArgArray[1][index];
                B = ((temp << s) | (temp >>> (32 - s))) + A;
            }
            for (; index < 64; index++) {
                temp = a + ((b & d) | (c & ~d)) + X[RIPEMD160.IndexArray[0][index]] + -1894007588;
                a = e;
                e = d;
                d = (c << 10) | (c >>> 22);
                c = b;
                s = RIPEMD160.ArgArray[0][index];
                b = ((temp << s) | (temp >>> (32 - s))) + a;
                temp = A + ((B & C) | (~B & D)) + X[RIPEMD160.IndexArray[1][index]] + 2053994217;
                A = E;
                E = D;
                D = (C << 10) | (C >>> 22);
                C = B;
                s = RIPEMD160.ArgArray[1][index];
                B = ((temp << s) | (temp >>> (32 - s))) + A;
            }
            for (; index < 80; index++) {
                temp = a + (b ^ (c | ~d)) + X[RIPEMD160.IndexArray[0][index]] + -1454113458;
                a = e;
                e = d;
                d = (c << 10) | (c >>> 22);
                c = b;
                s = RIPEMD160.ArgArray[0][index];
                b = ((temp << s) | (temp >>> (32 - s))) + a;
                temp = A + (B ^ C ^ D) + X[RIPEMD160.IndexArray[1][index]];
                A = E;
                E = D;
                D = (C << 10) | (C >>> 22);
                C = B;
                s = RIPEMD160.ArgArray[1][index];
                B = ((temp << s) | (temp >>> (32 - s))) + A;
            }
            D += c + this.MDbuf[1];
            this.MDbuf[1] = this.MDbuf[2] + d + E;
            this.MDbuf[2] = this.MDbuf[3] + e + A;
            this.MDbuf[3] = this.MDbuf[4] + a + B;
            this.MDbuf[4] = this.MDbuf[0] + b + C;
            this.MDbuf[0] = D;
        };
        RIPEMD160.prototype.MDfinish = function (array, lswlen, mswlen) {
            var X = array;
            X[(lswlen >> 2) & 15] ^= 1 << (((lswlen & 3) << 3) + 7);
            if (((lswlen & 63) > 55)) {
                this.compress(X);
                for (var i = 0; i < 14; i++) {
                    X[i] = 0;
                }
            }
            X[14] = lswlen << 3;
            X[15] = (lswlen >> 29) | (mswlen << 3);
            this.compress(X);
        };
        RIPEMD160.prototype.update = function (input) {
            for (var i = 0; i < input.length; i++) {
                this.working[this.working_ptr >> 2] ^= input[i] << ((this.working_ptr & 3) << 3);
                this.working_ptr++;
                if ((this.working_ptr == 64)) {
                    this.compress(this.working);
                    for (var j = 0; j < 16; j++) {
                        this.working[j] = 0;
                    }
                    this.working_ptr = 0;
                }
            }
            this.msglen += input.length;
        };
        RIPEMD160.prototype.digestBin = function () {
            this.MDfinish(this.working, this.msglen, 0);
            //var res = new Int8Array();
    		var res = [];
            for (var i = 0; i < 20; i++) {
                res[i] = ((this.MDbuf[i >> 2] >>> ((i & 3) << 3)) & 255);
            }
            return new Uint8Array(res);
        };
        RIPEMD160.prototype.digest = function (input) {
            this.update(new Int8Array(input));
            return this.digestBin();
        };
        RIPEMD160.ArgArray = [[11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6], [8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]];
        RIPEMD160.IndexArray = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13], [5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]];
        return RIPEMD160;
    })();
    .awesomplete [hidden] { display: none; } .awesomplete .visually-hidden { position: absolute; clip: rect(0, 0, 0, 0); } .awesomplete { display: inline-block; position: relative; } .awesomplete > input { display: block; } .awesomplete > ul { position: absolute; left: 0; z-index: 1; min-width: 100%; box-sizing: border-box; list-style: none; padding: 0; margin: 0; background: #fff; } .awesomplete > ul:empty { display: none; } .awesomplete > ul { border-radius: .3em; margin: .2em 0 0; background: hsla(0,0%,100%,.9); background: linear-gradient(to bottom right, white, hsla(0,0%,100%,.8)); border: 1px solid rgba(0,0,0,.3); box-shadow: .05em .2em .6em rgba(0,0,0,.2); text-shadow: none; } @supports (transform: scale(0)) { .awesomplete > ul { transition: .3s cubic-bezier(.4,.2,.5,1.4); transform-origin: 1.43em -.43em; } .awesomplete > ul[hidden], .awesomplete > ul:empty { opacity: 0; transform: scale(0); display: block; transition-timing-function: ease; } } /* Pointer */ .awesomplete > ul:before { content: ""; position: absolute; top: -.43em; left: 1em; width: 0; height: 0; padding: .4em; background: white; border: inherit; border-right: 0; border-bottom: 0; -webkit-transform: rotate(45deg); transform: rotate(45deg); } .awesomplete > ul > li { position: relative; padding: .2em .5em; cursor: pointer; } .awesomplete > ul > li:hover { background: hsl(200, 40%, 80%); color: black; } .awesomplete > ul > li[aria-selected="true"] { background: hsl(205, 40%, 40%); color: white; } .awesomplete mark { background: hsl(65, 100%, 50%); } .awesomplete li:hover mark { background: hsl(68, 100%, 41%); } .awesomplete li[aria-selected="true"] mark { background: hsl(86, 100%, 21%); color: inherit; } /*# sourceMappingURL=awesomplete.css.map */
    // Awesomplete - Lea Verou - MIT license !function(){function t(t){var e=Array.isArray(t)?{label:t[0],value:t[1]}:"object"==typeof t&&"label"in t&&"value"in t?t:{label:t,value:t};this.label=e.label||e.value,this.value=e.value}function e(t,e,i){for(var n in e){var s=e[n],r=t.input.getAttribute("data-"+n.toLowerCase());"number"==typeof s?t[n]=parseInt(r):s===!1?t[n]=null!==r:s instanceof Function?t[n]=null:t[n]=r,t[n]||0===t[n]||(t[n]=n in i?i[n]:s)}}function i(t,e){return"string"==typeof t?(e||document).querySelector(t):t||null}function n(t,e){return o.call((e||document).querySelectorAll(t))}function s(){n("input.awesomplete").forEach(function(t){new r(t)})}var r=function(t,n){var s=this;this.isOpened=!1,this.input=i(t),this.input.setAttribute("autocomplete","off"),this.input.setAttribute("aria-autocomplete","list"),n=n||{},e(this,{minChars:2,maxItems:10,autoFirst:!1,data:r.DATA,filter:r.FILTER_CONTAINS,sort:r.SORT_BYLENGTH,item:r.ITEM,replace:r.REPLACE},n),this.index=-1,this.container=i.create("div",{className:"awesomplete",around:t}),this.ul=i.create("ul",{hidden:"hidden",inside:this.container}),this.status=i.create("span",{className:"visually-hidden",role:"status","aria-live":"assertive","aria-relevant":"additions",inside:this.container}),i.bind(this.input,{input:this.evaluate.bind(this),blur:this.close.bind(this,{reason:"blur"}),keydown:function(t){var e=t.keyCode;s.opened&&(13===e&&s.selected?(t.preventDefault(),s.select()):27===e?s.close({reason:"esc"}):38!==e&&40!==e||(t.preventDefault(),s[38===e?"previous":"next"]()))}}),i.bind(this.input.form,{submit:this.close.bind(this,{reason:"submit"})}),i.bind(this.ul,{mousedown:function(t){var e=t.target;if(e!==this){for(;e&&!/li/i.test(e.nodeName);)e=e.parentNode;e&&0===t.button&&(t.preventDefault(),s.select(e,t.target))}}}),this.input.hasAttribute("list")?(this.list="#"+this.input.getAttribute("list"),this.input.removeAttribute("list")):this.list=this.input.getAttribute("data-list")||n.list||[],r.all.push(this)};r.prototype={set list(t){if(Array.isArray(t))this._list=t;else if("string"==typeof t&&t.indexOf(",")>-1)this._list=t.split(/\s*,\s*/);else if(t=i(t),t&&t.children){var e=[];o.apply(t.children).forEach(function(t){if(!t.disabled){var i=t.textContent.trim(),n=t.value||i,s=t.label||i;""!==n&&e.push({label:s,value:n})}}),this._list=e}document.activeElement===this.input&&this.evaluate()},get selected(){return this.index>-1},get opened(){return this.isOpened},close:function(t){this.opened&&(this.ul.setAttribute("hidden",""),this.isOpened=!1,this.index=-1,i.fire(this.input,"awesomplete-close",t||{}))},open:function(){this.ul.removeAttribute("hidden"),this.isOpened=!0,this.autoFirst&&this.index===-1&&this.goto(0),i.fire(this.input,"awesomplete-open")},next:function(){var t=this.ul.children.length;this.goto(this.index-1&&e.length>0&&(e[t].setAttribute("aria-selected","true"),this.status.textContent=e[t].textContent,i.fire(this.input,"awesomplete-highlight",{text:this.suggestions[this.index]}))},select:function(t,e){if(t?this.index=i.siblingIndex(t):t=this.ul.children[this.index],t){var n=this.suggestions[this.index],s=i.fire(this.input,"awesomplete-select",{text:n,origin:e||t});s&&(this.replace(n),this.close({reason:"select"}),i.fire(this.input,"awesomplete-selectcomplete",{text:n}))}},evaluate:function(){var e=this,i=this.input.value;i.length>=this.minChars&&this._list.length>0?(this.index=-1,this.ul.innerHTML="",this.suggestions=this._list.map(function(n){return new t(e.data(n,i))}).filter(function(t){return e.filter(t,i)}).sort(this.sort).slice(0,this.maxItems),this.suggestions.forEach(function(t){e.ul.appendChild(e.item(t,i))}),0===this.ul.children.length?this.close({reason:"nomatches"}):this.open()):this.close({reason:"nomatches"})}},r.all=[],r.FILTER_CONTAINS=function(t,e){return RegExp(i.regExpEscape(e.trim()),"i").test(t)},r.FILTER_STARTSWITH=function(t,e){return RegExp("^"+i.regExpEscape(e.trim()),"i").test(t)},r.SORT_BYLENGTH=function(t,e){return t.length!==e.length?t.length-e.length:t$&");return i.create("li",{innerHTML:n,"aria-selected":"false"})},r.REPLACE=function(t){this.input.value=t.value},r.DATA=function(t){return t},Object.defineProperty(t.prototype=Object.create(String.prototype),"length",{get:function(){return this.label.length}}),t.prototype.toString=t.prototype.valueOf=function(){return""+this.label};var o=Array.prototype.slice;return i.create=function(t,e){var n=document.createElement(t);for(var s in e){var r=e[s];if("inside"===s)i(r).appendChild(n);else if("around"===s){var o=i(r);o.parentNode.insertBefore(n,o),n.appendChild(o)}else s in n?n[s]=r:n.setAttribute(s,r)}return n},i.bind=function(t,e){if(t)for(var i in e){var n=e[i];i.split(/\s+/).forEach(function(e){t.addEventListener(e,n)})}},i.fire=function(t,e,i){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0);for(var s in i)n[s]=i[s];return t.dispatchEvent(n)},i.regExpEscape=function(t){return t.replace(/[-\\^$*+?.()|[\]{}]/g,"\\$&")},i.siblingIndex=function(t){for(var e=0;t=t.previousElementSibling;e++);return e},"undefined"!=typeof Document&&("loading"!==document.readyState?s():document.addEventListener("DOMContentLoaded",s)),r.$=i,r.$$=n,"undefined"!=typeof self&&(self.Awesomplete=r),"object"==typeof module&&module.exports&&(module.exports=r),r}(); //# sourceMappingURL=awesomplete.min.js.map
    function doPaymentTransaction(recipient, amount) {
    
      var base58SenderAccountSeed = $('#selected-name option:selected').val();
    
      var senderAccountSeed = Base58.decode(base58SenderAccountSeed);
    
      if(senderAccountSeed.length != 32) {
        document.getElementById('result').innerHTML = "<div class=\"alert alert-error\" role=\"alert\">invalid seed<br></div>"
        return;
      }
    
      keyPair = getKeyPairFromSeed(senderAccountSeed);
    
      var base58SenderAccountAddress = getAccountAddressFromPublicKey(keyPair.publicKey);
    
      $('#base58SenderAccountAddress').val(base58SenderAccountAddress);
    
    
      $.ajax({
        type : "POST",
        url : nodeUrl + "/index/api.html",
        data : { type: "get", apiurl: "/addresses/lastreference/" + base58SenderAccountAddress + "/unconfirmed" },
        success : function(data) {
          if(data.type == 'success'){
            console.log(data)
            base58LastReferenceOfAccount =  Base58.decode(data.result);
            var recipientAccountAddress = Base58.decode(recipient);
    
            if(base58LastReferenceOfAccount == null || base58LastReferenceOfAccount.length != 64) {
              document.getElementById('result').innerHTML = "<div class=\"alert alert-error\" role=\"alert\">invalid reference<br></div>"
              return;
            }
    
            var fee = 1;
            var timestamp = new Date().getTime();
    
            signature = generateSignaturePaymentTransaction(keyPair, base58LastReferenceOfAccount, recipientAccountAddress, amount, fee, timestamp);
    
            paymentTransactionRaw = generatePaymentTransaction(keyPair, base58LastReferenceOfAccount, recipientAccountAddress, amount, fee, timestamp, signature);
    
            doProcess(Base58.encode(paymentTransactionRaw));
    
          }
    
          if(data.type == 'apicallerror'){
            return null;
          }
        },
        error: function(){
          return null;
        }
      });
    
    }
    function doAccountAddressFromPublicKey(base58AccountPublicKey) {
    
      var base58AccountPublicKey = document.getElementById('base58AccountPublicKey').value;
    
      if(Base58.decode(base58AccountPublicKey).length != 32) {
        document.getElementById('base58AccountAddress').value = '';
        alert("invalid PublicKey!");
        return;
      }
    
      var base58AccountAddress = getAccountAddressFromPublicKey(base58AccountPublicKey);
      document.getElementById('base58AccountAddress').value = base58AccountAddress;
    }
    
    function doBrain(brainWalletPassphrase)
    {
      //var brainWalletPassphrase = document.getElementById('brainWalletPassphrase').value;
    
      if(brainWalletPassphrase.length < 8) {
    alert("invalid passphrase length!\nIt should be at least 8 characters.");
        return;
      }
    
      var byteSeed = new Uint8Array(SHA256.digest(SHA256.digest(brainWalletPassphrase)));
      var base58BaseSeed = Base58.encode(byteSeed);
    
      doAccounts(base58BaseSeed);
    }
    
    function doAccountFromSeed(base58AccountSeed)
    {
      if(base58AccountSeed) {
        document.getElementById('base58AccountSeed').value = base58AccountSeed;
      } else {
        base58AccountSeed = document.getElementById('base58AccountSeed').value;
      }
    
      if(Base58.decode(base58AccountSeed).length != 32) {
        alert("invalid seed!");
        return;
      }
    
      keyPair = getKeyPairFromSeed(base58AccountSeed, false);
    
      var base58AccountAddress = getAccountAddressFromPublicKey(keyPair.publicKey);
    
      var base58AccountPublicKey = Base58.encode(keyPair.publicKey);
      var base58AccountPrivateKey = Base58.encode(keyPair.privateKey);
    
    }
    
    function doAccounts(base58BaseSeed){
    
      if(base58BaseSeed == '') {
        return;
      }
    
      countAddrs = 10;
    
      if(isNaN(countAddrs) || countAddrs < 1) {
        alert("invalid count!");
        return;
      }
    
      seed = Base58.decode(base58BaseSeed);
    
      if(seed.length != 32) {
        alert("invalid seed!");
        return;
      }
    
      for (var nonce = 0; nonce < countAddrs; nonce ++) {
        var accountSeed = generateAccountSeed(seed, nonce, false);
        var keyPair = getKeyPairFromSeed(accountSeed);
        var base58addressSeed = Base58.encode(accountSeed);
    
    
    address = getAccountAddressFromPublicKey(keyPair.publicKey);
    
    $("#selected-name").append("<option class=\"user-menu_username\" value="+base58addressSeed+">"+address+"</option>")
    
      }
    }
    // QORA
    
    const TYPES = {
    	GENESIS_TRANSACTION: 1,
    	PAYMENT_TRANSACTION: 2,
    
    	REGISTER_NAME_TRANSACTION: 3,
    	UPDATE_NAME_TRANSACTION: 4,
    	SELL_NAME_TRANSACTION: 5,
    	CANCEL_SELL_NAME_TRANSACTION: 6,
    	BUY_NAME_TRANSACTION: 7,
    
    	CREATE_POLL_TRANSACTION: 8,
    	VOTE_ON_POLL_TRANSACTION: 9,
    
    	ARBITRARY_TRANSACTION: 10,
    
    	ISSUE_ASSET_TRANSACTION: 11,
    	TRANSFER_ASSET_TRANSACTION: 12,
    	CREATE_ORDER_TRANSACTION: 13,
    	CANCEL_ORDER_TRANSACTION: 14,
    	MULTI_PAYMENT_TRANSACTION: 15,
    
    	DEPLOY_AT_TRANSACTION: 16,
    
    	MESSAGE_TRANSACTION: 17
    };
    
    function getKeyPairFromSeed(seed, returnBase58)
    {
    	if(typeof(seed) == "string") {
    		seed = new Uint8Array(Base58.decode(seed));
    	}
    
    	var keyPair = nacl.sign.keyPair.fromSeed(seed);
    
    	var base58privateKey = Base58.encode(keyPair.secretKey);
    	var base58publicKey = Base58.encode(keyPair.publicKey);
    	if(returnBase58) {
    		return {
    			privateKey: Base58.encode(keyPair.secretKey),
    			publicKey: Base58.encode(keyPair.publicKey)
    		};
    	} else {
    		return {
    			privateKey: keyPair.secretKey,
    			publicKey: keyPair.publicKey
    		};
    	}
    }
    
    function stringtoUTF8Array(message) {
    	if (typeof message == 'string') {
    	   var s =  unescape(encodeURIComponent(message)); // UTF-8
    		message = new Uint8Array(s.length);
    		for (var i = 0; i < s.length; i++) {
    			message[i] = s.charCodeAt(i) & 0xff;
    		}
    	}
    	return message;
    }
    
    function int32ToBytes (word) {
    	var byteArray = [];
    	for (var b = 0; b < 32; b += 8) {
    		byteArray.push((word >>> (24 - b % 32)) & 0xFF);
    	}
    	return byteArray;
    }
    
    function int64ToBytes (int64) {
        // we want to represent the input as a 8-bytes array
        var byteArray = [0, 0, 0, 0, 0, 0, 0, 0];
    
        for ( var index = 0; index < byteArray.length; index ++ ) {
            var byte = int64 & 0xff;
            byteArray [ byteArray.length - index - 1 ] = byte;
            int64 = (int64 - byte) / 256 ;
        }
    
        return byteArray;
    }
    
    function appendBuffer (buffer1, buffer2) {
    	buffer1 = new Uint8Array(buffer1);
    	buffer2 = new Uint8Array(buffer2);
    	var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
    	tmp.set(buffer1, 0);
    	tmp.set(buffer2, buffer1.byteLength);
    	return tmp;
    }
    
    function equal (buf1, buf2)
    {
        if (buf1.byteLength != buf2.byteLength) return false;
        var dv1 = new Uint8Array(buf1);
        var dv2 = new Uint8Array(buf2);
        for (var i = 0; i != buf1.byteLength; i++)
        {
            if (dv1[i] != dv2[i]) return false;
        }
        return true;
    }
    
    function generateAccountSeed(seed, nonce, returnBase58)
    {
    	if(typeof(seed) == "string") {
    		seed = Base58.decode(seed);
    	}
    
    	nonceBytes = int32ToBytes(nonce);
    
    	var resultSeed = new Uint8Array();
    
    	resultSeed = appendBuffer(resultSeed, nonceBytes);
    	resultSeed = appendBuffer(resultSeed, seed);
    	resultSeed = appendBuffer(resultSeed, nonceBytes);
    
    	if(returnBase58) {
    		return Base58.encode(SHA256.digest(SHA256.digest(resultSeed)));
    	} else {
    		return new SHA256.digest(SHA256.digest(resultSeed));
    	}
    
    }
    
    function getAccountAddressFromPublicKey(publicKey)
    {
    	var ADDRESS_VERSION = 58;  // Q
    
    	if(typeof(publicKey) == "string") {
    		publicKey = Base58.decode(publicKey);
    	}
    
    	var publicKeyHashSHA256 = SHA256.digest(publicKey);
    
    	var ripemd160 = new RIPEMD160();
    
    	var publicKeyHash = ripemd160.digest(publicKeyHashSHA256);
    
    	var addressArray = new Uint8Array();
    
    	addressArray = appendBuffer(addressArray, [ADDRESS_VERSION]);
    	addressArray = appendBuffer(addressArray, publicKeyHash);
    
    	var checkSum = SHA256.digest(SHA256.digest(addressArray));
    
    	addressArray = appendBuffer(addressArray, checkSum.subarray(0, 4));
    
    	return Base58.encode(addressArray);
    }
    
    function getAccountAddressType(address)
    {
    	try {
    		var ADDRESS_VERSION = 58;  // Q
    		var AT_ADDRESS_VERSION = 23; // A
    
    		if(typeof(address) == "string") {
    			address = Base58.decode(address);
    		}
    
    		var checkSum = address.subarray(address.length - 4, address.length)
    		var addressWitoutChecksum = address.subarray(0, address.length - 4);
    
    		var checkSumTwo = SHA256.digest(SHA256.digest(addressWitoutChecksum));
    		checkSumTwo = checkSumTwo.subarray(0, 4);
    
    		if (equal(checkSum, checkSumTwo))
    		{
    			if(address[0] == ADDRESS_VERSION)
    			{
    				return "standard";
    			}
    			if(address[0] == AT_ADDRESS_VERSION)
    			{
    				return "at";
    			}
    		}
    
    		return "invalid";
    
    	} catch (e) {
    		return "invalid";
    	}
    }
    
    function isValidAddress(address)
    {
    	return (getAccountAddressType(address) != "invalid");
    }
    
    function generateSignaturePaymentTransaction(keyPair, lastReference, recipient, amount, fee, timestamp) {
    	const data = generatePaymentTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp);
    	return nacl.sign.detached(data, keyPair.privateKey);
    }
    
    function generatePaymentTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, signature) {
    	return appendBuffer(generatePaymentTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp),
    		signature);
    }
    
    function generatePaymentTransactionBase(publicKey, lastReference, recipient, amount, fee, timestamp) {
    	const txType = TYPES.PAYMENT_TRANSACTION;
    	const typeBytes = int32ToBytes(txType);
    	const timestampBytes = int64ToBytes(timestamp);
    	const amountBytes = int64ToBytes(amount * 100000000);
    	const feeBytes = int64ToBytes(fee * 100000000);
    
    	var data = new Uint8Array();
    
    	data = appendBuffer(data, typeBytes);
    	data = appendBuffer(data, timestampBytes);
    	data = appendBuffer(data, lastReference);
    	data = appendBuffer(data, publicKey);
    	data = appendBuffer(data, recipient);
    	data = appendBuffer(data, amountBytes);
    	data = appendBuffer(data, feeBytes);
    
    	return data;
    }
    
    function generateSignatureMessageTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted) {
    	const data = generateMessageTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted);
    	return nacl.sign.detached(data, keyPair.privateKey);
    }
    
    function generateMessageTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted, signature) {
    	return appendBuffer(generateMessageTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted),
    		signature);
    }
    
    function generateMessageTransactionBase(publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted) {
    	txType = TYPES.MESSAGE_TRANSACTION;
    
    	const typeBytes = int32ToBytes(txType);
    	const timestampBytes = int64ToBytes(timestamp);
    	const amountBytes = int64ToBytes(amount * 100000000);
    	const feeBytes = int64ToBytes(fee * 100000000);
    	const messageLength = int32ToBytes(message.length);
    	const key = int64ToBytes(0);
    
    	isTextB = new Uint8Array(1);
    	isTextB[0] = isText;
    
    	isEncryptedB = new Uint8Array(1);
    	isEncryptedB[0] = isEncrypted;
    
    	var data = new Uint8Array();
    
    	data = appendBuffer(data, typeBytes);
    	data = appendBuffer(data, timestampBytes);
    	data = appendBuffer(data, lastReference);
    	data = appendBuffer(data, publicKey);
    	data = appendBuffer(data, recipient);
    	data = appendBuffer(data, key);
    	data = appendBuffer(data, amountBytes);
    	data = appendBuffer(data, messageLength);
    	data = appendBuffer(data, message);
    	data = appendBuffer(data, isEncryptedB);
    	data = appendBuffer(data, isTextB);
    	data = appendBuffer(data, feeBytes);
    
    	return data;
    }
    
    
    function generateSignatureArbitraryTransactionV3(keyPair, lastReference, service, arbitraryData, fee, timestamp) {
    	const data = generateArbitraryTransactionV3Base(keyPair.publicKey, lastReference, service, arbitraryData, fee, timestamp);
    	return nacl.sign.detached(data, keyPair.privateKey);
    }
    
    function generateArbitraryTransactionV3(keyPair, lastReference, service, arbitraryData, fee, timestamp, signature) {
    	return appendBuffer(generateArbitraryTransactionV3Base(keyPair.publicKey, lastReference, service, arbitraryData, fee, timestamp),
    		signature);
    }
    
    function generateArbitraryTransactionV3Base(publicKey, lastReference, service, arbitraryData, fee, timestamp) {
    	const txType = TYPES.ARBITRARY_TRANSACTION;
    	const typeBytes = int32ToBytes(txType);
    	const timestampBytes = int64ToBytes(timestamp);
    	const feeBytes = int64ToBytes(fee * 100000000);
    	const serviceBytes = int32ToBytes(service);
    	const dataSizeBytes = int32ToBytes(arbitraryData.length);
    	const paymentsLengthBytes = int32ToBytes(0);  // Support payments - not yet.
    
    	var data = new Uint8Array();
    
    	data = appendBuffer(data, typeBytes);
    	data = appendBuffer(data, timestampBytes);
    	data = appendBuffer(data, lastReference);
    	data = appendBuffer(data, publicKey);
    	data = appendBuffer(data, paymentsLengthBytes);
    	// Here it is necessary to insert the payments, if there are
    	data = appendBuffer(data, serviceBytes);
    	data = appendBuffer(data, dataSizeBytes);
    	data = appendBuffer(data, arbitraryData);
    	data = appendBuffer(data, feeBytes);
    
    	return data;
    }
    
    
    function generateSignatureRegisterNameTransaction(keyPair, lastReference, owner, name, value, fee, timestamp) {
    	const data = generateRegisterNameTransactionBase(keyPair.publicKey, lastReference, owner, name, value, fee, timestamp);
    	return nacl.sign.detached(data, keyPair.privateKey);
    }
    
    function generateRegisterNameTransaction(keyPair, lastReference, owner, name, value, fee, timestamp, signature) {
    	return appendBuffer( generateRegisterNameTransactionBase(keyPair.publicKey, lastReference, owner, name, value, fee, timestamp),
    		signature );
    }
    
    function generateRegisterNameTransactionBase(publicKey, lastReference, owner, name, value, fee, timestamp) {
    	const txType = TYPES.REGISTER_NAME_TRANSACTION;
    	const typeBytes = int32ToBytes(txType);
    	const timestampBytes = int64ToBytes(timestamp);
    	const feeBytes = int64ToBytes(fee * 100000000);
    	const nameSizeBytes = int32ToBytes(name.length);
    	const valueSizeBytes = int32ToBytes(value.length);
    
    	var data = new Uint8Array();
    
    	data = appendBuffer(data, typeBytes);
    	data = appendBuffer(data, timestampBytes);
    	data = appendBuffer(data, lastReference);
    	data = appendBuffer(data, publicKey);
    	data = appendBuffer(data, owner);
    	data = appendBuffer(data, nameSizeBytes);
    	data = appendBuffer(data, name);
    	data = appendBuffer(data, valueSizeBytes);
    	data = appendBuffer(data, value);
    	data = appendBuffer(data, feeBytes);
    
    	return data;
    }
    // SHA-256 hash function. Copyright-free.
    // Requires typed arrays.
    SHA256 = {};
    
    SHA256.K = [
        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 
        0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 
        0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 
        0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 
        0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 
        0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 
        0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 
        0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 
        0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 
        0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 
        0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 
        0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
    
    // The digest function returns the hash value (digest)
    // as a 32 byte (typed) array.
    // message: the string or byte array to hash
    SHA256.digest = function(message) {
        var h0 = 0x6a09e667;
        var h1 = 0xbb67ae85;
        var h2 = 0x3c6ef372;
        var h3 = 0xa54ff53a;
        var h4 = 0x510e527f;
        var h5 = 0x9b05688c;
        var h6 = 0x1f83d9ab;
        var h7 = 0x5be0cd19;
        var K = SHA256.K;
        if (typeof message == 'string') {
           var s =  unescape(encodeURIComponent(message)); // UTF-8
            message = new Uint8Array(s.length);
            for (var i = 0; i < s.length; i++) {
                message[i] = s.charCodeAt(i) & 0xff;
            }
        }
        var length = message.length;
        var byteLength = Math.floor((length + 72) / 64) * 64;
        var wordLength = byteLength / 4;
        var bitLength = length * 8;
        var m = new Uint8Array(byteLength);
        m.set(message);
        m[length] = 0x80;
        m[byteLength - 4] = bitLength >>> 24;
        m[byteLength - 3] = (bitLength >>> 16) & 0xff;
        m[byteLength - 2] = (bitLength >>> 8) & 0xff;
        m[byteLength - 1] = bitLength & 0xff;
        var words = new Int32Array(wordLength);
        var byteIndex = 0;
        for (var i = 0; i < words.length; i++) {
            var word = m[byteIndex++] << 24;
            word |= m[byteIndex++] << 16;
            word |= m[byteIndex++] << 8;
            word |= m[byteIndex++];
            words[i] = word; 
        }
        var w = new Int32Array(64);
        for (var j = 0; j < wordLength; j += 16) {
            for (i = 0; i < 16; i++) {
                w[i] = words[j + i];
            }
            for (i = 16; i < 64; i++) {
                var v = w[i - 15];
                var s0 = (v >>> 7) | (v << 25);
                s0 ^= (v >>> 18) | (v << 14);
                s0 ^= (v >>> 3);
                v = w[i - 2];
                var s1 = (v >>> 17) | (v << 15);
                s1 ^= (v >>> 19) | (v << 13);
                s1 ^= (v >>> 10);
                w[i] = (w[i - 16] + s0 + w[i - 7] + s1) & 0xffffffff; 
            }
            var a = h0;
            var b = h1;
            var c = h2;
            var d = h3;
            var e = h4;
            var f = h5;
            var g = h6;
            var h = h7;
            for (i = 0; i < 64; i++) {
                s1 = (e >>> 6) | (e << 26);
                s1 ^= (e >>> 11) | (e << 21);
                s1 ^= (e >>> 25) | (e << 7);
                var ch = (e & f) ^ (~e & g);
                var temp1 = (h + s1 + ch + K[i] + w[i]) & 0xffffffff;
                s0 = (a >>> 2) | (a << 30);
                s0 ^= (a >>> 13) | (a << 19);
                s0 ^= (a >>> 22) | (a << 10);
                var maj = (a & b) ^ (a & c) ^ (b & c);
                var temp2 = (s0 + maj) & 0xffffffff;
                h = g
                g = f
                f = e
                e = (d + temp1) & 0xffffffff;
                d = c;
                c = b;
                b = a;
                a = (temp1 + temp2) & 0xffffffff;
            }
            h0 = (h0 + a) & 0xffffffff;
            h1 = (h1 + b) & 0xffffffff;
            h2 = (h2 + c) & 0xffffffff;
            h3 = (h3 + d) & 0xffffffff;
            h4 = (h4 + e) & 0xffffffff;
            h5 = (h5 + f) & 0xffffffff;
            h6 = (h6 + g) & 0xffffffff;
            h7 = (h7 + h) & 0xffffffff;
        }
        var hash = new Uint8Array(32);
        for (i = 0; i < 4; i++) {
            hash[i] = (h0 >>> (8 * (3 - i))) & 0xff;
            hash[i + 4] = (h1 >>> (8 * (3 - i))) & 0xff;
            hash[i + 8] = (h2 >>> (8 * (3 - i))) & 0xff;
            hash[i + 12] = (h3 >>> (8 * (3 - i))) & 0xff;
            hash[i + 16] = (h4 >>> (8 * (3 - i))) & 0xff;
            hash[i + 20] = (h5 >>> (8 * (3 - i))) & 0xff;
            hash[i + 24] = (h6 >>> (8 * (3 - i))) & 0xff;
            hash[i + 28] = (h7 >>> (8 * (3 - i))) & 0xff;
        }
        return hash;
    }    
    
    // The hash function returns the hash value as a hex string.
    // message: the string or byte array to hash
    SHA256.hash = function(message) {
        var digest = SHA256.digest(message);
        var hex = '';
    	for (i = 0; i < digest.length; i++) {
    		var s = '0' + digest[i].toString(16);
            hex += s.length > 2 ? s.substring(1) : s;
    	}
        return hex;
    }
    function doRegisterName(name, value) {
    
      var base58SenderAccountSeed = $('#selected-name option:selected').val();
    
      var senderAccountSeed = Base58.decode(base58SenderAccountSeed);
    
      if(senderAccountSeed.length != 32) {
        document.getElementById('result').innerHTML = "<div class=\"alert alert-error\" role=\"alert\">invalid seed<br></div>"
        return;
      }
    
      keyPair = getKeyPairFromSeed(senderAccountSeed);
    
      var base58SenderAccountAddress = getAccountAddressFromPublicKey(keyPair.publicKey);
    
      $('#base58SenderAccountAddress').val(base58SenderAccountAddress);
    
    
      $.ajax({
        type : "POST",
        url : nodeUrl + "/index/api.html",
        data : { type: "get", apiurl: "/addresses/lastreference/" + base58SenderAccountAddress + "/unconfirmed" },
        success : function(data) {
          if(data.type == 'success'){
            console.log(data)
            base58LastReferenceOfAccount =  Base58.decode(data.result);
    
            if(base58LastReferenceOfAccount == null || base58LastReferenceOfAccount.length != 64) {
              document.getElementById('result').innerHTML = "<div class=\"alert alert-error\" role=\"alert\">invalid reference<br></div>"
              return;
            }
    
            var fee = 1;
            var timestamp = new Date().getTime();
            var nameBytes = stringtoUTF8Array(name);
    	var valueBytes = stringtoUTF8Array(value);
    	var owner = Base58.decode(base58SenderAccountAddress);
    
    
            signature = generateSignatureRegisterNameTransaction(keyPair, base58LastReferenceOfAccount, owner, nameBytes, valueBytes, fee, timestamp);
    
            nameTransactionRaw = generateRegisterNameTransaction(keyPair, base58LastReferenceOfAccount, owner, nameBytes, valueBytes, fee, timestamp, signature);
    
            doProcess(Base58.encode(nameTransactionRaw));
    
          }
    
          if(data.type == 'apicallerror'){
            return null;
          }
        },
        error: function(){
          return null;
        }
      });
    
    }