/******************************************************************************
 * Copyright © 2014-2016 The SuperNET Developers.                             *
 *                                                                            *
 * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at                  *
 * the top-level directory of this distribution for the individual copyright  *
 * holder information and the developer policies on copyright and licensing.  *
 *                                                                            *
 * Unless otherwise agreed in a custom licensing agreement, no part of the    *
 * SuperNET software, including this file may be copied, modified, propagated *
 * or distributed except according to the terms contained in the LICENSE file *
 *                                                                            *
 * Removal or modification of this copyright notice is prohibited.            *
 *                                                                            *
 ******************************************************************************/
#include "pangea777.h"

bits256 cards777_initcrypt(bits256 data,bits256 privkey,bits256 pubkey,int32_t invert)
{
    bits256 hash;
    hash = curve25519_shared(privkey,pubkey);
    if ( invert != 0 )
        hash = crecip_donna(hash);
    return(fmul_donna(data,hash));
}

bits256 cards777_cardpriv(bits256 playerpriv,bits256 *cardpubs,int32_t numcards,bits256 cipher)
{
    bits256 cardpriv,checkpub; int32_t i;
    for (i=0; i<numcards; i++)
    {
        cardpriv = cards777_initcrypt(cipher,playerpriv,cardpubs[i],1);
        //printf("(%llx %llx) ",(long long)cardpriv.txid,(long long)curve25519_shared(playerpriv,cardpubs[i]).txid);
        checkpub = curve25519(cardpriv,curve25519_basepoint9());
        if ( memcmp(checkpub.bytes,cardpubs[i].bytes,sizeof(bits256)) == 0 )
        {
            //printf("%d ",cardpriv.bytes[1]);
            //printf("decrypted card.%d %llx\n",cardpriv.bytes[1],(long long)cardpriv.txid);
            return(cardpriv);
        }
    }
    //printf("\nplayerpriv %llx cipher.%llx\n",(long long)playerpriv.txid,(long long)cipher.txid);
    memset(cardpriv.bytes,0,sizeof(cardpriv));
    return(cardpriv);
}

int32_t cards777_checkcard(bits256 *cardprivp,int32_t cardi,int32_t slot,int32_t destplayer,bits256 playerpriv,bits256 *cardpubs,int32_t numcards,bits256 card)
{
    bits256 cardpriv;
    cardpriv = cards777_cardpriv(playerpriv,cardpubs,numcards,card);
    if ( cardpriv.txid != 0 )
    {
        if ( slot >= 0 && destplayer != slot )
            printf(">>>>>>>>>>>> ERROR ");
        if ( Debuglevel > 2 )
            printf("slot.%d B DECODED cardi.%d destplayer.%d cardpriv.[%d]\n",slot,cardi,destplayer,cardpriv.bytes[1]);
        *cardprivp = cardpriv;
        return(cardpriv.bytes[1]);
    }
    memset(cardprivp,0,sizeof(*cardprivp));
    return(-1);
}

int32_t cards777_validate(bits256 cardpriv,bits256 final,bits256 *cardpubs,int32_t numcards,bits256 *audit,int32_t numplayers,bits256 playerpub)
{
    int32_t i; bits256 val,checkcard,ver;
    val = final;
    for (i=numplayers-1; i>0; i--)
    {
        val = fmul_donna(audit[i],val);
        //if ( memcmp(tmp.bytes,audit[i-1].bytes,sizeof(tmp)) != 0 )
        //    printf("cards777_validate: mismatched audit[%d] %llx vs %llx %llx\n",i-1,(long long)tmp.txid,(long long)audit[i-1].txid,(long long)audit[i].txid);
    }
    checkcard = val;//fcontract(val);
    if ( memcmp(checkcard.bytes,audit[0].bytes,sizeof(checkcard)) != 0 )
    {
        printf("cards777_validate: checkcard not validated %llx vs %llx numplayers.%d\n",(long long)checkcard.txid,(long long)audit[0].txid,numplayers);
        return(-1);
    }
    ver = cards777_initcrypt(cardpriv,cardpriv,playerpub,0);
    if ( memcmp(checkcard.bytes,ver.bytes,sizeof(checkcard)) != 0 )
    {
        printf("cards777_validate: ver not validated %llx vs %llx\n",(long long)checkcard.txid,(long long)ver.txid);
        return(-1);
    }
    return(cardpriv.bytes[1]);
}

int32_t cards777_shuffle(bits256 *shuffled,bits256 *cards,int32_t numcards,int32_t N)
{
    int32_t i,j,pos,nonz,permi[CARDS777_MAXCARDS],desti[CARDS777_MAXCARDS]; uint8_t x; uint64_t mask;
    memset(desti,0,sizeof(desti));
    for (i=0; i<numcards; i++)
        desti[i] = i;
    for (i=0; i<numcards; i++)
    {
        OS_randombytes(&x,1);
        pos = (x % ((numcards-1-i) + 1));
        //printf("%d ",pos);
        permi[i] = desti[pos];
        desti[pos] = desti[numcards-1 - i];
        desti[numcards-1 - i] = -1;
    }
    //printf("pos\n");
    for (mask=i=nonz=0; i<numcards; i++)
    {
        if ( 0 && Debuglevel > 2 )
            printf("%d ",permi[i]);
        mask |= (1LL << permi[i]);
        for (j=0; j<N; j++,nonz++)
            shuffled[nonz] = cards[permi[i]*N + j];//, printf("%llx ",(long long)shuffled[nonz].txid);
    }
    if ( Debuglevel > 2 )
        printf("shuffled mask.%llx err.%llx\n",(long long)mask,(long long)(mask ^ ((1LL<<numcards)-1)));
    return(0);
}

void cards777_layer(bits256 *layered,bits256 *xoverz,bits256 *incards,int32_t numcards,int32_t N)
{
    int32_t i,k,nonz = 0; bits256 z_x;
    for (i=nonz=0; i<numcards; i++)
    {
        for (k=0; k<N; k++,nonz++)
        {
            xoverz[nonz] = xoverz_donna(rand256(1));
            z_x = crecip_donna(xoverz[nonz]);
            layered[nonz] = fmul_donna(z_x,incards[nonz]);
            //printf("{%llx -> %llx}.%d ",(long long)incards[nonz].txid,(long long)layered[nonz].txid,nonz);
        }
        //printf("card.%d\n",i);
    }
}

int32_t cards777_calcmofn(struct supernet_info *myinfo,uint8_t *allshares,uint8_t *myshares[],uint8_t *sharenrs,int32_t M,bits256 *xoverz,int32_t numcards,int32_t N)
{
    int32_t size,j; uint8_t space[8192];
    size = N * sizeof(bits256) * numcards;
    calc_shares(myinfo,allshares,(void *)xoverz,size,size,M,N,sharenrs,space,sizeof(space)); // PM &allshares[playerj * size] to playerJ
    for (j=0; j<N; j++)
        myshares[j] = &allshares[j * size];
    return(size);
}

uint8_t *cards777_recover(uint8_t *shares[],uint8_t *sharenrs,int32_t M,int32_t numcards,int32_t N)
{
    void *G; int32_t i,size; uint8_t *recover,recovernrs[255],space[8192];
    size = N * sizeof(bits256) * numcards;
    if ( (recover= calloc(1,size)) == 0 )
    {
        printf("cards777_recover: unexpected out of memory error\n");
        return(0);
    }
    memset(recovernrs,0,sizeof(recovernrs));
    for (i=0; i<N; i++)
        if ( shares[i] != 0 )
            recovernrs[i] = sharenrs[i];
    G = gfshare_ctx_initdec(recovernrs,N,size,space,sizeof(space));
    for (i=0; i<N; i++)
        if ( shares[i] != 0 )
            gfshare_ctx_dec_giveshare(G,i,shares[i]);
    gfshare_ctx_dec_newshares(G,recovernrs);
    gfshare_ctx_decextract(0,0,G,recover);
    gfshare_ctx_free(G);
    return(recover);
}

bits256 cards777_pubkeys(bits256 *pubkeys,int32_t numcards,bits256 cmppubkey)
{
    int32_t i; bits256 bp,pubkey,hash,check,prod;
    memset(check.bytes,0,sizeof(check));
    memset(bp.bytes,0,sizeof(bp)), bp.bytes[0] = 9;
    prod = fmul_donna(bp,crecip_donna(bp));
    for (i=0; i<numcards; i++)
    {
        pubkey = pubkeys[i];
        vcalc_sha256(0,hash.bytes,pubkey.bytes,sizeof(pubkey));
        hash.bytes[0] &= 0xf8, hash.bytes[31] &= 0x7f, hash.bytes[31] |= 64;
        prod = fmul_donna(prod,hash);
    }
    check = prod;
    if ( cmppubkey.txid != 0 )
    {
        if ( memcmp(check.bytes,cmppubkey.bytes,sizeof(check)) != 0 )
            printf("cards777_pubkeys: mismatched pubkeys permicheck.%llx != prod.%llx\n",(long long)check.txid,(long long)pubkey.txid);
        //else printf("pubkeys matched\n");
    }
    return(check);
}

bits256 cards777_initdeck(bits256 *cards,bits256 *cardpubs,int32_t numcards,int32_t N,bits256 *playerpubs,bits256 *playerprivs)
{
    char buf[4096]; bits256 privkey,pubkey,hash, bp,prod; int32_t i,j,nonz,num = 0; uint64_t mask = 0;
    bp = curve25519_basepoint9();
    prod = crecip_donna(bp);
    prod = fmul_donna(bp,prod);
    if ( Debuglevel > 2 )
        printf("card777_initdeck unit.%llx\n",(long long)prod.txid);
    nonz = 0;
    while ( mask != (1LL << numcards)-1 )
    {
        privkey = curve25519_keypair(&pubkey);
        buf[0] = 0;
        if ( (i=privkey.bytes[1]) < numcards && ((1LL << i) & mask) == 0 )
        {
            mask |= (1LL << i);
            cardpubs[num] = pubkey;
            if ( playerprivs != 0 )
                sprintf(buf+strlen(buf),"%llx.",(long long)privkey.txid);
            for (j=0; j<N; j++,nonz++)
            {
                cards[nonz] = cards777_initcrypt(privkey,privkey,playerpubs[j],0);
                if ( playerprivs != 0 )
                    sprintf(buf+strlen(buf),"[%llx * %llx -> %llx] ",(long long)cards[nonz].txid,(long long)curve25519_shared(playerprivs[j],pubkey).txid,(long long)cards777_initcrypt(cards[nonz],playerprivs[j],pubkey,1).txid);
            }
            vcalc_sha256(0,hash.bytes,pubkey.bytes,sizeof(pubkey));
            hash.bytes[0] &= 0xf8, hash.bytes[31] &= 0x7f, hash.bytes[31] |= 64;
            prod = fmul_donna(prod,hash);
            //printf("(%s) num.%d [%llx] %d prod.%llx\n",buf,num,(long long)mask ^ ((1LL << numcards)-1),i,(long long)prod.txid);
            num++;
        }
    }
    if ( playerprivs != 0 )
        printf("\n%llx %llx playerprivs\n",(long long)playerprivs[0].txid,(long long)playerprivs[1].txid);
    //if ( 0 && Debuglevel > 2 )
    {
        for (i=0; i<numcards; i++)
            printf("%d ",cards[i*N].bytes[1]);
        printf("init order %llx (%llx %llx)\n",(long long)prod.txid,(long long)playerpubs[0].txid,(long long)playerpubs[1].txid);
    }
    return(prod);
}

uint8_t *cards777_encode(struct supernet_info *myinfo,bits256 *encoded,bits256 *xoverz,uint8_t *allshares,uint8_t *myshares[],uint8_t sharenrs[255],int32_t M,bits256 *ciphers,int32_t numcards,int32_t N)
{
    bits256 shuffled[CARDS777_MAXCARDS * CARDS777_MAXPLAYERS];
    cards777_shuffle(shuffled,ciphers,numcards,N);
    cards777_layer(encoded,xoverz,shuffled,numcards,N);
    memset(sharenrs,0,255);
    init_sharenrs(sharenrs,0,N,N);
    cards777_calcmofn(myinfo,allshares,myshares,sharenrs,M,xoverz,numcards,N);
    memcpy(ciphers,shuffled,numcards * N * sizeof(bits256));
    if ( 0 )
    {
        /*{
            init_hexbytes_noT(nrs,dp->hand.sharenrs,dp->N);
            if ( (nrs= jstr(json,"sharenrs")) != 0 )
                decode_hex(dp->hand.sharenrs,(int32_t)strlen(nrs)>>1,nrs);
        }*/
        int32_t i,j,m,size; uint8_t *recover,*testshares[CARDS777_MAXPLAYERS],testnrs[255];
        size = N * sizeof(bits256) * numcards;
        for (j=0; j<1; j++)
        {
            memset(testnrs,0,sizeof(testnrs));
            memset(testshares,0,sizeof(testshares));
            m = (rand() % N) + 1;
            if ( m < M )
                m = M;
            if ( init_sharenrs(testnrs,sharenrs,m,N) < 0 )
            {
                printf("iter.%d error init_sharenrs(m.%d of n.%d)\n",j,m,N);
                return(0);
            }
            for (i=0; i<N; i++)
                if ( testnrs[i] == sharenrs[i] )
                    testshares[i] = myshares[i];
            if ( (recover= cards777_recover(testshares,sharenrs,M,numcards,N)) != 0 )
            {
                if ( memcmp(xoverz,recover,size) != 0 )
                    fprintf(stderr,"(ERROR m.%d M.%d N.%d)\n",m,M,N);
                else fprintf(stderr,"reconstructed with m.%d M.%d N.%d\n",m,M,N);
                free(recover);
            } else printf("nullptr from cards777_recover\n");
        }
    }
    return(allshares);
}

bits256 cards777_decode(bits256 *seedp,bits256 *xoverz,int32_t destplayer,bits256 cipher,bits256 *outcards,int32_t numcards,int32_t N)
{
    int32_t i,ind;
    memset(seedp->bytes,0,sizeof(*seedp));
    for (i=0; i<numcards; i++)
    {
        ind = i*N + destplayer;
        //printf("[%llx] ",(long long)outcards[ind].txid);
        if ( memcmp(outcards[ind].bytes,cipher.bytes,32) == 0 )
        {
            *seedp = xoverz[ind];
            cipher = fmul_donna(xoverz[ind],cipher);
            //printf("matched %d -> %llx\n",i,(long long)cipher.txid);
            return(cipher);
        }
    }
    if ( i == numcards )
    {
        printf("decryption error %llx: destplayer.%d no match\n",(long long)cipher.txid,destplayer);
        memset(cipher.bytes,0,sizeof(cipher));
        //cipher = cards777_cardpriv(playerpriv,cardpubs,numcards,cipher);
    }
    return(cipher);
}

#ifdef notyet
struct cards777_privdata *cards777_allocpriv(int32_t numcards,int32_t N)
{
    struct cards777_privdata *priv;
    if ( (priv= calloc(1,sizeof(*priv) + sizeof(bits256) * (2*((N * numcards * N) + (N * numcards))))) == 0 )
    {
        printf("cards777_allocpriv: unexpected out of memory error\n");
        return(0);
    }
    priv->audits = &priv->data[0];
    priv->outcards = &priv->audits[N * numcards * N];
    priv->xoverz = &priv->outcards[N * numcards];
    priv->allshares = (void *)&priv->xoverz[N * numcards]; // N*numcards*N
    return(priv);
}

struct cards777_pubdata *cards777_allocpub(int32_t M,int32_t numcards,int32_t N)
{
    struct cards777_pubdata *dp;
    if ( (dp= calloc(1,sizeof(*dp) + sizeof(bits256) * ((numcards + 1) + (N * numcards)))) == 0 )
    {
        printf("cards777_allocpub: unexpected out of memory error\n");
        return(0);
    }
    dp->M = M, dp->N = N, dp->numcards = numcards;
    dp->hand.cardpubs = &dp->data[0];
    dp->hand.final = &dp->hand.cardpubs[numcards + 1];
    return(dp);
}

int32_t cards777_testinit(struct hostnet777_server *srv,int32_t M,struct hostnet777_client **clients,int32_t N,int32_t numcards)
{
    //static int64_t balances[9];
    int32_t i; uint8_t sharenrs[255]; //,destplayer,cardibits256 *ciphers,cardpriv,card; uint64_t mask = 0;
    struct cards777_pubdata *dp; //struct cards777_privdata *priv; struct pangea_info *sp;
    if ( srv->num != N )
    {
        printf("srv->num.%d != N.%d\n",srv->num,N);
        return(-1);
    }
    memset(sharenrs,0,sizeof(sharenrs));
    init_sharenrs(sharenrs,0,N,N); // this needs to be done to start a hand
    for (i=0; i<N; i++)
    {
        dp = srv->clients[i].pubdata = cards777_allocpub(M,numcards,N);
        //sp = dp->table;
        memcpy(dp->hand.sharenrs,sharenrs,dp->N);
        /*for (j=0; j<N; j++)
            sp->playerpubs[j] = srv->clients[j].pubkey;
        for (j=0; j<N; j++)
        {
            balances[j] = 100;
            dp->balances[j] = &balances[j];
        }*/
        printf("deprecated, need to init sp->\n");
        //priv = srv->clients[i].privdata = cards777_allocpriv(numcards,N);
        //priv->privkey = (i == 0) ? srv->H.privkey : clients[i]->H.privkey;
        /*if ( i == 0 )
            dp->checkprod = cards777_initdeck(priv->outcards,dp->cardpubs,numcards,N,dp->playerpubs), refdp = dp;
        else memcpy(dp->cardpubs,refdp->cardpubs,sizeof(*dp->cardpubs) * numcards);*/
    }
    return(0);
    /*priv = srv->clients[0].privdata;
    ciphers = priv->outcards;
    for (i=1; i<N; i++)
    {
        dp = srv->clients[i].pubdata;
        priv = srv->clients[i].privdata;
        cards777_encode(priv->outcards,priv->xoverz,priv->allshares,priv->myshares,dp->sharenrs,dp->M,ciphers,dp->numcards,dp->N);
        ciphers = priv->outcards;
    }
    for (cardi=0; cardi<dp->numcards; cardi++)
    {
        for (destplayer=0; destplayer<dp->N; destplayer++)
        {
            priv = srv->clients[dp->N - 1].privdata;
            card = priv->outcards[cardi*dp->N + destplayer];
            for (i=N-1; i>=0; i--)
            {
                j = (i > 0) ? i : destplayer;
                //printf("cardi.%d destplayer.%d i.%d j.%d\n",cardi,destplayer,i,j);
                dp = srv->clients[j].pubdata;
                priv = srv->clients[j].privdata;
                cardpriv = cards777_cardpriv(priv->privkey,dp->cardpubs,dp->numcards,card);
                if ( cardpriv.txid != 0 )
                {
                    mask |= (1LL << cardpriv.bytes[1]);
                    if ( destplayer != j )
                        printf(">>>>>>>>>>>> ERROR ");
                    printf("i.%d j.%d A DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask);
                    break;
                }
                card = cards777_decode(priv->xoverz,destplayer,card,priv->outcards,dp->numcards,dp->N);
                cardpriv = cards777_cardpriv(priv->privkey,dp->cardpubs,dp->numcards,card);
                if ( cardpriv.txid != 0 )
                {
                    mask |= (1LL << cardpriv.bytes[1]);
                    if ( destplayer != j )
                        printf(">>>>>>>>>>>> ERROR ");
                    printf("i.%d j.%d B DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask);
                    break;
                }
            }
        }
        printf("cardi.%d\n\n",cardi);
    }*/
    return(0);
}

void cards777_initid(struct hostnet777_id *id,bits256 pubkey,struct cards777_pubdata *dp,struct cards777_privdata *priv)
{
    id->pubkey = pubkey;
    id->nxt64bits = acct777_nxt64bits(pubkey);
    id->pubdata = dp;
    id->privdata = priv;
    id->pmsock = -1;
}

void cards777_test()
{
    int32_t i,j,vals[52][52]; bits256 keypairs[52][2],otherpairs[52][2],matrix[52][52]; char buf[512];
    FILE *fp;
    if ( (fp= fopen("/persistent/test","rb")) != 0 )
    {
        if ( fread(buf,6,1,fp) <= 0 )
            printf("read error for /persistent/test\n");
        buf[6] = 0;
        printf("test exists (%s)\n",buf);
        fclose(fp);
    } else printf("testfile not present\n");
    for (i=0; i<52; i++)
        keypairs[i][0] = curve25519_keypair(&keypairs[i][1]);
    for (j=0; j<52; j++)
        otherpairs[j][0] = curve25519_keypair(&otherpairs[j][1]);
    bits256 zmone;zmone = crecip_donna(keypairs[0][0]);
    printf("DEBUG.%d %llx vs %llx | %llx -> %llx/%llx\n",Debuglevel,(long long)keypairs[0][0].txid,(long long)fcontract(fexpand(keypairs[0][0])).txid,(long long)zmone.txid,(long long)fexpand(fmul_donna(keypairs[0][0],zmone)).txid,(long long)fmul(fexpand(keypairs[0][0]),fexpand(zmone)).txid);
    for (i=0; i<52; i++)
    {break;
        buf[0] = 0;
        for (j=0; j<52; j++)
        {
            matrix[i][j] = fmul_donna(keypairs[j][1],otherpairs[i][1]);
            vals[i][j] = matrix[i][j].bytes[1] % 52;
            sprintf(buf+strlen(buf),"%d ",vals[i][j]);
        }
        printf("%s\n",buf);
    }
    struct hostnet777_server *srv;  int32_t M,N = 9; //struct hostnet777_client **clients;
    struct cards777_pubdata *dp; struct cards777_privdata *priv;
    bits256 checkprod,cards[52],playerpubs[9],playerprivs[9];
    //clients = calloc(N+1,sizeof(*clients));
    if ( (srv= hostnet777_server(keypairs[0][0],keypairs[0][1],0,0,0,N)) == 0 )
    {
        printf("cant create hostnet777 server\n");
        return;
    }
    M = (N >> 1) + 1;
    for (i=0; i<N; i++)
    {
        cards777_initid(&srv->clients[i],keypairs[i][1],cards777_allocpub(M,52,N),cards777_allocpriv(52,N));
        playerprivs[i] = keypairs[i][0];
        playerpubs[i] = keypairs[i][1];
        if ( i == 0 )
        {
            srv->H.privkey = keypairs[i][0];
            srv->H.pubkey = keypairs[i][1];
        }
        else
        {
        }
    }
    dp = srv->clients[0].pubdata;
    dp->N = N; dp->M = M; dp->numcards = 52;
    checkprod = cards777_initdeck(cards,dp->hand.cardpubs,52,N,playerpubs,0);
    printf("deck initialzed %llx\n",(long long)checkprod.txid);
    uint8_t sharenrs[255]; uint64_t mask = 0; int32_t cardi,destplayer;
    bits256 card,cardpriv,seed,*ciphers = cards;
    for (i=1; i<N; i++)
    {
        dp = srv->clients[i].pubdata;
        dp->N = N; dp->M = M; dp->numcards = 52;
        priv = srv->clients[i].privdata;
        cards777_encode(priv->outcards,priv->xoverz,priv->allshares,priv->myshares,sharenrs,dp->M,ciphers,dp->numcards,dp->N);
        ciphers = priv->outcards;
    }
    printf("deck encrypted\n");
    for (cardi=0; cardi<dp->numcards; cardi++)
    {
        for (destplayer=0; destplayer<dp->N; destplayer++)
        {
            priv = srv->clients[dp->N - 1].privdata;
            card = priv->outcards[cardi*dp->N + destplayer];
            for (i=N-1; i>=0; i--)
            {
                j = (i > 0) ? i : destplayer;
                //printf("cardi.%d destplayer.%d i.%d j.%d\n",cardi,destplayer,i,j);
                dp = srv->clients[j].pubdata;
                priv = srv->clients[j].privdata;
                cardpriv = cards777_cardpriv(keypairs[j][0],dp->hand.cardpubs,dp->numcards,card);
                if ( cardpriv.txid != 0 )
                {
                    mask |= (1LL << cardpriv.bytes[1]);
                    if ( destplayer != j )
                        printf(">>>>>>>>>>>> ERROR ");
                    printf("i.%d j.%d A DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask);
                    break;
                }
                card = cards777_decode(&seed,priv->xoverz,destplayer,card,priv->outcards,dp->numcards,dp->N);
                cardpriv = cards777_cardpriv(keypairs[j][0],dp->hand.cardpubs,dp->numcards,card);
                if ( cardpriv.txid != 0 )
                {
                    mask |= (1LL << cardpriv.bytes[1]);
                    if ( destplayer != j )
                        printf(">>>>>>>>>>>> ERROR ");
                    printf("i.%d j.%d B DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask);
                    break;
                }
            }
        }
        printf("cardi.%d\n\n",cardi);
        break;
    }
}

#endif