From 4678bc1612608fd06f7c39bdc4352975b0356f86 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:59:48 +0000 Subject: [PATCH 01/44] Translate src/qt/locale/bitcoin_en.ts in pt_PT 100% reviewed source file: 'src/qt/locale/bitcoin_en.ts' on 'pt_PT'. --- src/qt/locale/bitcoin_pt_PT.ts | 2664 +++++++++++++++++++++++++++++--- 1 file changed, 2434 insertions(+), 230 deletions(-) diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts index 3737f96cad..8439e176bd 100644 --- a/src/qt/locale/bitcoin_pt_PT.ts +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -1,11 +1,18 @@ - + AboutDialog + About Gridcoin Sobre o Gridcoin + + <b>Gridcoin</b> + <b>Gridcoin</b> + + + This is experimental software. @@ -23,14 +30,17 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em AdditionalFieldsTableDataModel + Name Nome + Value Valor + Required Requerido @@ -38,83 +48,103 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em AddressBookPage + Create a new address Criar um novo endereço + &New &Novo + Copy the currently selected address to the system clipboard Copiar o endereço selecionado para a área de transferência + &Copy &Copiar + Show &QR Code Mostrar Código &QR + Sign a message to prove you own a Gridcoin address Assine a mensagem para provar que possui um endereço Gridcoin + Sign &Message Assinar &Mensagem + Verify a message to ensure it was signed with a specified Gridcoin address Verifica a mensagem para assegurar que foi assinada por um endereço Gridcoin especificado + &Verify Message &Verificar Mensagem + Delete the currently selected address from the list Elimina o endereço selecionado da lista + Address Book Livro de Endereços + These are your Gridcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. Estes são os seus endereços do Gridcoin para receber pagamentos. Pode dar diferentes nomes a cada remetente, para que saiba quem lhe está a pagar. + Double-click to edit label Duplo clique para editar a etiqueta + &Delete &Eliminar + Copy &Label Copiar &Etiqueta + &Edit &Editar + Export Address Book Data Exportar Dados do Livro de Endereços + Comma separated file Name of CSV file format Ficheiro separado por vírgulas + Error exporting Erro ao exportar + Could not write to file %1. Não foi possível escrever para o ficheiro %1. @@ -122,14 +152,17 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em AddressTableModel + Label Etiqueta + Address Endereço + (no label) (sem etiqueta) @@ -137,102 +170,134 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em AskPassphraseDialog + Passphrase Dialog Diálogo da Frase de Segurança + Enter passphrase Insira a frase de segurança + New passphrase Nova frase de segurança + Repeat new passphrase Repita a nova frase de segurança + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. Serve para desabilitar o envio trivial de dinheiro quando o SO está comprometido. Não fornece uma segurança real. + For staking only Apenas para realizar stake + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. Insira a nova frase de segurança para a carteira. <br/> Por favor, utilize uma frase de segurança de <b>10 ou mais carateres aleatórios,</b> ou <b>oito ou mais palavras</b>. + Encrypt wallet Encriptar carteira + This operation needs your wallet passphrase to unlock the wallet. Esta operação precisa da frase de segurança da sua carteira para desbloqueá-la. + Unlock wallet Desbloquear carteira + Change passphrase Modificar frase de segurança + Enter the old and new passphrase to the wallet. Escreva a frase de segurança da carteira antiga, seguida da nova. + Confirm wallet encryption Confirmar encriptação da carteira + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! Aviso: Se encriptar a sua carteira e perder a frase de segurança, irá <b>PERDER TODAS AS SUAS MOEDAS</b>! + Are you sure you wish to encrypt your wallet? Tem a certeza que deseja encriptar a sua carteira? + + Wallet encrypted Carteira encriptada + Gridcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. O Gridcoin irá agora terminar o processo de encriptação. Lembre-se que encriptar a sua carteira não garante que as suas moedas não possam ser roubadas por um malware que infete o seu computador. + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. IMPORTANTE: Qualquer cópia de segurança feita ao ficheiro da carteira, deverá ser substituído pelo novo ficheiro, atualmente encriptado na carteira. Por razões de segurança, cópias de segurança não encriptadas efetuadas anteriormente do ficheiro da carteira tornar-se-ão inúteis assim que começar a usar a nova carteira encriptada. + + + + Wallet encryption failed Encriptação da carteira falhou + Wallet encryption failed due to an internal error. Your wallet was not encrypted. A encriptação da carteira falhou devido a um erro interno. A sua carteira não foi encriptada. + + The supplied passphrases do not match. As frases de segurança fornecidas não coincidem. + Wallet unlock failed Desbloqueio da carteira falhou + + The passphrase entered for the wallet decryption was incorrect. A frase de segurança introduzida para a desencriptação da carteira estava incorreta. + Wallet passphrase was successfully changed. A frase de segurança da carteira foi alterada com sucesso. + + Warning: The Caps Lock key is on! Aviso: A tecla Caps Lock está ligada! @@ -240,6 +305,12 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em BanTableModel + + IP/Netmask + IP/Netmask + + + Banned Until Banido Até @@ -247,352 +318,430 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em BitcoinGUI + A fatal error occurred. Gridcoin can no longer continue safely and will quit. Ocorreu um erro fatal. O Gridcoin não consegue continuar em segurança e irá fechar. + + Gridcoin + Gridcoin + + + Wallet Carteira + &Overview &Resumo + Show general overview of wallet Mostrar resumo geral da carteira + &Send &Enviar + Send coins to a Gridcoin address Enviar moedas para um endereço Gridcoin + &Receive &Receber + Show the list of addresses for receiving payments Mostrar lista de endereços de pagamentos recebidos + &History &Histórico + Browse transaction history Explorar histórico das transações + &Favorites &Favoritos + Edit the list of stored addresses and labels Editar a lista de endereços armazenados e etiquetas + &Voting &Votação + Voting Votação + &Block Explorer &Explorador de Blocos + Block Explorer Explorador de Blocos + &Exchange &Cambiar + + Web Site - Website + Sítio Web + &Web Site - &Website + &Site Web + &GRC Chat Room &Sala de Chat GRC + GRC Chatroom Sala de Chat GRC + + &BOINC + &BOINC + + + Gridcoin rewards distributed computing with BOINC Recompensas Gridcoin distribuídas por computação com o BOINC + E&xit S&air + Quit application Sair da aplicação + &About Gridcoin &Sobre o Gridcoin + Show information about Gridcoin Mostrar informações sobre o Gridcoin + &Diagnostics &Diagnósticos + Diagnostics Diagnósticos + &Options... &Opções... + Modify configuration options for Gridcoin Modificar opções de configuração do Gridcoin + Open config &file... Abrir &ficheiro de configuração... + Open the config file in your standard editor Abrir o ficheiro de configuração no seu editor base + &Researcher Wizard... &Assistente de Pesquisa... + Open BOINC and beacon settings for Gridcoin Abrir definições do BOINC e do beacon para o Gridcoin + &Show / Hide &Mostrar / Ocultar + &Encrypt Wallet... &Encriptar Carteira... + Encrypt wallet Encriptar carteira + &Backup Wallet/Config... &Cópia de Segurança da Carteira/Configuração... + Backup wallet/config to another location Cópia de segurança da carteira/configuração para outra localização + &Change Passphrase... &Alterar Frase de Segurança... + Change the passphrase used for wallet encryption Alterar a frase de segurança utilizada na encriptação da carteira + &Unlock Wallet... &Desbloquear Carteira... + Unlock wallet Desbloquear carteira + &Lock Wallet &Bloquear Carteira + Lock wallet Bloquear carteira + Sign &message... Assinar &mensagem... + &Verify message... &Verificar mensagem... + &Export... &Exportar... + Export the data in the current tab to a file Exportar os dados na aba atual para um ficheiro + &Debug window &Janela de Depuração + Open debugging and diagnostic console Abrir consola de diagnóstico e depuração + &Snapshot Download Transferência do &Snapshot + Download and apply latest snapshot Transferir e aplicar o último snapshot + &Reset blockchain data - &Repor dados da blockchain + &Repor dados da cadeia de blocos + Remove blockchain data and start chain from zero - Remover dados da blockchain e começar a cadeira do zero + Remover dados da cadeia de blocos e começar a cadeia do zero + &Mask values &Mascarar valores + Mask the values in the Overview screen Mascarar os valores no ecrã de Visão Geral + &File &Ficheiro + &Settings &Configurações + &Community &Comunidade + &Help &Ajuda + Open menu. Abrir menu. + Toggle light/dark mode. Trocar modo claro/escuro. + Not staking: Miner is not initialized. Não realizando stake: Mineração não foi inicializada. + Not staking: Disabled by configuration. Não realizando stake: Desabilitado por configuração. + + [testnet] [rede de testes] + + Gridcoin client Cliente Gridcoin + No active connections to the Gridcoin network. If this persists more than a few minutes, please check your configuration and your network connectivity. Sem ligações ativas à rede do Gridcoin. Se isto persistir por mais dum que uns minutos, por favor verifique a sua configuração e a conetividade à rede. + %n active connection(s) to the Gridcoin network - - %n ligação ativa à rede do Gridcoin - %n ligações ativas à rede do Gridcoin - + %n ligação ativa à rede do Gridcoin%n ligações ativas à rede do Gridcoin%n ligações ativas à rede do Gridcoin + Sync: no connections. Sincronização: sem conexões + Processed %n block(s) of transaction history. - - %n bloco(s) processado(s) do histórico de transações. - %n bloco(s) processado(s) do histórico de transações. - + %n bloco(s) processado(s) do histórico de transações.%n bloco(s) processado(s) do histórico de transações.%n bloco(s) processado(s) do histórico de transações. + %n second(s) ago - - %n segundo(s) atrás - %n segundo(s) atrás - + %n segundo(s) atrás%n segundo(s) atrás%n segundo(s) atrás + %n minute(s) ago - - %n minuto(s) atrás - %n minuto(s) atrás - + %n minuto(s) atrás%n minuto(s) atrás%n minuto(s) atrás + %n hour(s) ago - - %n hora(s) atrás - %n hora(s) atrás - + %n hora(s) atrás%n hora(s) atrás%n hora(s) atrás + %n day(s) ago - - %n dia(s) atrás - %n dia(s) atrás - + %n dia(s) atrás%n dia(s) atrás%n dia(s) atrás + Up to date Atualizado + Catching up... Recuperando o atraso... + Last received block was generated %1. O último bloco recebido foi gerado há %1. + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? Esta transação excede o limite de tamanho. Pode continuar a enviar com uma taxa de %1, que vais para os nós que processam a sua transação e ajudam a suportar a rede. Tem a certeza que quer pagar a taxa? + Confirm transaction fee Confirmar taxa de transação + Sent transaction Transação enviada + Incoming transaction Transação recebida + Date: %1 Amount: %2 Type: %3 @@ -603,134 +752,173 @@ Tipo: %3 Endereço: %4 + Do you wish to download and apply the latest snapshot? If yes the wallet will shutdown and perform the task. Quer transferir e aplicar o último snapshot? Se sim, a carteira irá encerrar e executar a tarefa. + Warning: Canceling after stage 2 will result in sync from 0 or corrupted blockchain files. - Aviso: Cancelar depois do 2º passo irá resultar em sincronizar tudo do "0", ou ficheiros corrompidos no blockchain. + Aviso: Cancelar depois do 2º passo irá resultar em sincronizar tudo do "0", ou ficheiros corrompidos na cadeia de blocos. + Do you want to delete blockchain data and sync from zero? - Tem a certeza que quer eliminar os dados da blockchain e começar a sincronização do zero? + Tem a certeza que quer eliminar os dados da cadeia de blocos e começar a sincronização do zero? + Warning: After the blockchain data is deleted, the wallet will shutdown and when restarted will begin syncing from zero. Your balance will temporarily show as 0 GRC while syncing. - Aviso: Depois dos dados da blockchain serem eliminados, a carteira irá encerrar e ao reiniciar, irá começar a sincronizar do zero. O seu balanço irá temporariamente aparecer como 0 GRC enquanto sincroniza. + Aviso: Depois dos dados da cadeia de blocos serem eliminados, a carteira irá encerrar e ao reiniciar, irá começar a sincronizar do zero. O seu balanço irá temporariamente aparecer como 0 GRC enquanto sincroniza. + Close Confirmation Fechar Confirmação + Exit the Gridcoin wallet? Fechar a carteira Gridcoin? + + URI handling Tratamento do URI + + URI can not be parsed! This can be caused by an invalid Gridcoin address or malformed URI parameters. O URI não pode ser analisado! Isto pode ser causado por um endereço inválido de Gridcoin ou parâmetros de URI mal formados. + Wallet is <b>not encrypted</b>! A Carteira está <b>não encriptada</b>! + Wallet is <b>encrypted</b> and currently %1 A Carteira está <b>encriptada</b> e atualmente %1 + <b>unlocked for staking only</b> <b>desbloqueada para realizar stake apenas</b> + <b>fully unlocked</b> <b>completamente desbloqueada</b> + Wallet is <b>encrypted</b> and currently <b>locked</b> A carteira está <b>encriptada</b> e atualmente <b>bloqueada</b> + Backup Wallet Cópia de Segurança da Carteira + Wallet Data (*.dat) Dados da Carteira (*.dat) + + Backup Failed Cópia de Segurança Falhou + + There was an error trying to save the wallet data to the new location. Houve um erro ao tentar guardar os dados da carteira para uma nova localização. + Backup Config Configuração da Cópia de Segurança + Wallet Config (*.conf) Configuração da Carteira (*.conf) + not available indisponível + year ano + month mês + day dia + hour hora + %1 times per %2 %1 vezes por %2 + Staking.<br>Your weight is %1<br>Network weight is %2<br><b>Estimated</b> staking frequency is %3. A realizar stake. <br>O seu peso é %1<br>Peso da rede é %2<br><b>Frequência</b> estimada de stake é de %3. + Unable to stake: %1 Impossível de realizar stake: %1 + Not staking currently: %1, <b>Estimated</b> staking frequency is %2. Não está a realizar stake atualmente: %1, <b>Frequência</b> estimada de stake é de %2. + + + none nenhum + Scraper: waiting on wallet to sync. Scraper: aguardando que a carteira sincronize. + Scraper: superblock not needed - inactive. Scraper: superbloco desnecessário - inativo + Scraper: downloading and processing stats. Scraper: transferindo e processando estado. + Scraper: Convergence achieved, date/time %1 UTC. Project(s) excluded: %2. Scrapers included: %3. @@ -743,16 +931,26 @@ Scrapers excluídos: %4. Scrapers a não produzir: %5. + Scraper: Convergence achieved, date/time %1 UTC. Project(s) excluded: %2. Scraper: Convergência alcançada, data/hora %1 UTC. Projeto(s) excluído(s): %2. + Scraper: No convergence able to be achieved. Will retry in a few minutes. Scraper: Convergência não alcançada. Irá tentar novamente em alguns minutos. + + CPID: %1 +Time left to activate: %2%3 + CPID: %1 +Tempo restante para ativar: %2%3 + + + CPID: %1 Beacon age: %2 Current beacon expired! @@ -763,6 +961,7 @@ Idade do Beacon: %2 %3 + CPID: %1 Beacon age: %2 Expires: %3 @@ -773,25 +972,30 @@ Expira: %3 %4 + New Poll - Nova Votação + Nova Sondagem + A new poll is available. Open Gridcoin to vote. - Uma nova votação está disponível. Abra o Gridcoin para votar. + Uma nova sondagem está disponível. Abra o Gridcoin para votar. ClientModel + Network Alert Alerta de Rede + Low difficulty!; Dificuldade baixa!; + Miner: Minerador: @@ -799,154 +1003,214 @@ Expira: %3 CoinControlDialog + Quantity: Quantidade: + + Bytes: + Bytes: + + + Amount: Quantia: + Fee: Taxa: + Coin Control Controlo de Moedas + Low Output: Baixa Produção: + After Fee: Depois da Taxa: + Change: Modificar: + Toggles between selecting all and selecting none. Mudar entre selecionar todos e nenhum. + + Select All Selecionar Todos + Tree &mode &Modo de árvore + Select inputs Selecionar entradas + + <= + <= + + + Filters the already selected inputs. Filtra as entradas já selecionadas. + Filter Filtro + + Pushing this button after making a input selection either manually or with the filter will present a destination address list where you specify a single address as the destination for the consolidated output. The send (Pay To) entry will be filled in with this address and you can finish the consolidation by pressing the send button. + Ao premir este botão depois de fazer uma seleção de entrada manualmente ou com o filtro, é apresentada uma lista de endereços de destino onde pode especificar um único endereço como destino para a saída consolidada. A entrada de envio (Pagar a) será preenchida com este endereço e pode terminar a consolidação premindo o botão de enviar. + + + Consolidate Consolidado + The consolidation transaction is ready to send to self. Please press the ok button to go to the send dialog. A transação de consolidação está preparada para ser enviada para si. Por favor, clique no botão de ok para ir para o diálogo de envio. + Ready to consolidate Pronto para consolidar + Amount Quantia + Date Data + Confirmations Confirmações + Confirmed Confirmada + Label Etiqueta + &List mode &Lista de modo + Address Endereço + Copy address Copiar endereço + Copy label Copiar etiqueta + + Copy amount Copiar quantia + Copy transaction ID Copiar ID da transação + Copy quantity Copiar quantidade + Copy fee Copiar taxa + Copy after fee Copiar depois da taxa + Copy bytes Copiar bytes + Copy low output Copiar baixa produção + Copy change Copiar modificação + + Flips the filter mode between selecting inputs less than or equal to the provided value (<=) and greater than or equal to the provided value (>=). The filter also automatically limits the number of inputs to %1, in ascending order for <= and descending order for >=. + Alterna o modo de filtro entre a seleção de entradas menores ou iguais ao valor fornecido (<=) e maiores ou iguais ao valor fornecido (>=). O filtro também limita automaticamente o número de entradas a %1, em ordem crescente para <= e decrescente para >=. + + + Select None Não Selecionar Nenhum + DUST INSIGNIFICANTE + yes sim + no não + This label turns red, if the transaction size is bigger than 10000 bytes. This means a fee of at least %1 per kb is required. @@ -959,6 +1223,7 @@ Isto significa que uma taxa de pelos menos %1 por kb é necessária. Pode variar +/- 1Byte por entrada + This label turns red, if any recipient receives an amount smaller than %1. This means a fee of at least %2 is required. @@ -971,6 +1236,7 @@ Isto significa que uma taxa de pelo menos %2 é necessária. Quantias 0.546 vezes menores que o mínimo, são mostradas como INSIGNIFICANTES. + This label turns red, if the change is smaller than %1. This means a fee of at least %2 is required. @@ -979,14 +1245,18 @@ Quantias 0.546 vezes menores que o mínimo, são mostradas como INSIGNIFICANTES. Isto significa que uma taxa de pelo menos %2 é necessária. + + (no label) (sem etiqueta) + change from %1 (%2) alterar de %1 (%2) + (change) (modificar) @@ -994,22 +1264,27 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ConsolidateUnspentDialog + Consolidate Unspent Outputs (UTXOs) Consolidar Saídas Não Gastas (UTXOs) + Select Destination Address for Consolidation Selecionar Endereço de Destino de Consolidação + Label Etiqueta + Address Endereço + Note: The number of inputs selected for consolidation has been limited to %1 to prevent a transaction failure due to too many inputs. Nota: O número de entradas selecionado para consolidação foi limitado a %1, para prevenir uma falha de transação devido a demasiadas entradas. @@ -1017,6 +1292,7 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ConsolidateUnspentWizard + Consolidate Unspent Transaction Outputs (UTXOs) Consolidar Saídas Não Gastas (UTXOs) @@ -1024,22 +1300,34 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ConsolidateUnspentWizardSelectDestinationPage + WizardPage Página do Assistente + + Step 2: Select the destination address for the consolidation transaction. Note that all of the selected inputs will be consolidated to an output on this address. If there is a very small amount of change (due to uncertainty in the fee calculation), it will also be sent to this address. If you selected inputs only from a particular address on the previous page, then that address will already be selected by default. + Passo 2: Selecionar o endereço de destino para a transação de consolidação. Note que todas as entradas selecionadas serão consolidadas numa saída neste endereço. Se houver um valor muito pequeno de mudança (devido à incerteza no cálculo da taxa), ele também será enviado para este endereço. Se na página anterior tiver selecionado apenas entradas de um determinado endereço, esse endereço já estará selecionado por defeito. + + + + Label Etiqueta + + Address Endereço + Currently selected: Selecionado atualmente: + isComplete estáConcluído @@ -1047,98 +1335,144 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ConsolidateUnspentWizardSelectInputsPage + WizardPage Página do Assistente + Step 1: Select the inputs to be consolidated. Remember that the inputs to the consolidation are your unspent outputs (UTXOs) in your wallet. Passo 1: Selecionar as entradas a serem consolidadas. Lembre-se que as entradas para consolidação, são as saídas não gastas (UTXOs) na sua carteira. + + Select All Selecionar Todos + Tree Mode Modo de Árvore + List Mode Modo de Lista + Select inputs Selecionar entradas + + <= + <= + + + Filters the already selected inputs. Filtra as entradas já selecionadas. + Filter Filtro + Amount Quantia + Label Etiqueta + Address Endereço + Date Data + Confirmations Confirmações + Confirmed Confirmada + Quantity Quantidade + + 99999 + 99999 + + + Fee Taxa + + 99.9999 + 99.9999 + + + After Fee Amount Quantia Depois da Taxa + + 999999999.9999 + 999999999.9999 + + + isComplete estáConcluído + Note: The number of inputs selected for consolidation has been limited to %1 to prevent a transaction failure due to too many inputs. Nota: O número de entradas selecionadas para consolidação foi limitado a %1, para prevenir falhas de transação devido a demasiadas entradas. + Note: The number of inputs selected for consolidation is currently more than the limit of %1. Please use the filter or manual selection to reduce the number of inputs to %1 or less to prevent a transaction failure due to too many inputs. Nota: O número de entradas selecionadas para consolidação é atualmente maior que o limite de %1. Por favor utilize o filtro ou seleção manual para reduzir o número de entradas para %1 ou menos, para prevenir uma falha de transação devido a demasiadas entradas. + Select None Não Selecionar Nenhum + + (no label) (sem etiqueta) + change from %1 (%2) alterar de %1 (%2) + (change) (modificar) @@ -1146,38 +1480,62 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ConsolidateUnspentWizardSendPage + WizardPage Página do Assistente + Step 3: Confirm Consolidation Transaction Details. Transaction will be ready to send when Finish is pressed. Passo 3: Confirmar os detalhes da transação de consolidação. A transação estará pronta quando o Terminar for pressionado. + Number of Inputs Número de Entradas + + 999999 + 999999 + + + Transaction Fee Taxa de Transação + + 99.9999 + 99.9999 + + + Amount Quantia + + 999999999.9999 + 999999999.9999 + + + Destination Address Endereço de Destino + address endereço + Destination Address Label Etiqueta do Endereço de Destino + label etiqueta @@ -1185,98 +1543,123 @@ Isto significa que uma taxa de pelo menos %2 é necessária. DiagnosticsDialog + + Diagnostics Diagnósticos + Verify outbound port works A verificar que as portas de saída estão a funcionar + Check total connections A verificar total de ligaçoes + Verify CPID has active beacon A verificar que o CPID tem um beacon ativo + Verify BOINC path A verificar a diretoria do BOINC + Check outbound connections A verificar ligaçoes de saída + Check difficulty a verificar dificuldade + Verify CPID has RAC A verificar que o CPID tem RAC + Overall Result Resultado Geral + Verify wallet is synced A verificar que a carteira está sincronizada + Verify CPID is valid A verificar que o CPID é válido + Verify clock A verificar data/hora + Check client version A verificar versão do cliente + Check estimated time to stake A verificar tempo estimado para realizar stake + Close Fechar + Test Testar + Testing... Testando... + N/A N/D + Passed Sucesso + Warning Aviso + Failed Falhou + One or more tests have generated a warning status. Wallet operation may be degraded. Please see the individual test tooltips for details and recommended action(s). - Um ou mais testes geraram um estado de alerta. Operações com a carteira podem estar corrompidas. Por favor, veja as dicas individuais de teste para detalhes e ações recomendadas. + Um ou mais testes geraram um estado de alerta. Operações com a carteira podem estar corrompidas. Por favor, consulte as dicas individuais de teste para detalhes e ações recomendadas. + One or more tests have failed. Proper wallet operation may be significantly degraded or impossible. Please see the individual test tooltips for details and recommended action(s). - Um ou mais testes falharam. Operações adequadas com a carteira, podem estar signifcamente degradadas ou impossiveis. Por favor, veja as dicas indivuais de teste para detalhes e ações recomendadas. + Um ou mais testes falharam. Operações adequadas com a carteira, podem estar significativamente degradadas ou impossíveis. Por favor, consulte as dicas individuais de teste para detalhes e ações recomendadas. + All tests passed. Your wallet operation is normal. Todos os testes concluídos. A operação da sua carteira está normal. @@ -1284,54 +1667,67 @@ Isto significa que uma taxa de pelo menos %2 é necessária. EditAddressDialog + Edit Address Editar Endereço + &Label &Etiqueta + The label associated with this address book entry A etiqueta associada a esta entrada do livro de endereços + The address associated with this address book entry. This can only be modified for sending addresses. O endereço associado com esta entrada no livro. Pode ser modificado apenas para endereços de envio. + &Address &Endereço + New receiving address Novo endereço de receção + New sending address Novo endereço de envio + Edit receiving address Editar endereço de receção + Edit sending address Editar endereço de envio - The entered address "%1" is not a valid Gridcoin address. - O endereço inserido "%1" não é um endereço de Gridcoin válido. + + The entered address "%1" is not a valid Gridcoin address. + O endereço inserido "%1" não é um endereço de Gridcoin válido. - The entered address "%1" is already in the address book. - O endereço introduzido "%1" já se encontra no livro de endereços. + + The entered address "%1" is already in the address book. + O endereço introduzido "%1" já se encontra no livro de endereços. + Could not unlock wallet. Não foi possível desbloquear a carteira. + New key generation failed. A criação de uma nova chave falhou. @@ -1339,10 +1735,13 @@ Isto significa que uma taxa de pelo menos %2 é necessária. FavoritesPage + + Favorites Favoritos + Search by address or label Pesquisar por endereço ou etiqueta @@ -1350,6 +1749,7 @@ Isto significa que uma taxa de pelo menos %2 é necessária. Form + Form Formulário @@ -1357,18 +1757,22 @@ Isto significa que uma taxa de pelo menos %2 é necessária. FreespaceChecker + A new data directory will be created. Uma nova diretoria de dados irá ser criada. + Directory already exists. If this directory contains valid data, it will be used. Diretoria já existente. Se esta diretoria tiver dados válidos, será usada. + Path already exists, and is not a directory. Caminho já existente, e não é uma diretoria. + Cannot create data directory here. Não é possível criar diretoria aqui. @@ -1376,77 +1780,133 @@ Isto significa que uma taxa de pelo menos %2 é necessária. GUIUtil::HelpMessageBox + version versão + Usage: Utilização: + command-line options opções da linha de comandos - + + + Gridcoin + Gridcoin + + Intro + Welcome Bem-vindo. + Welcome to %1. Bem-vindo a %1. + As this is the first time the program is launched, you can choose where %1 will store its data. Como é a primeira vez que o programa é lançado, pode escolher onde %1 irá armazenar os dados. + Use the default data directory Utilizar a diretoria de dados predefinida + Use a custom data directory: Utilizar uma diretoria de dados personalizada: - Error: Specified data directory "%1" cannot be created. - Erro: Diretoria de dados especificada "%1" não pode ser criada. + + When you click OK, %1 will begin to download and process the full %4 block chain (~%2GB), either from genesis in %3, or the last synchronized block, if this was a preexisting data directory. + Quando clicar em OK, %1 começará a transferir e a processar toda a cadeia de blocos %4 (~%2GB), quer a partir da génese em %3, ou a partir do último bloco sincronizado, se este for um diretório de dados pré-existente. + + The synchronization is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off. + A sincronização é muito exigente e pode expor problemas de hardware do seu computador que anteriormente tivessem passado despercebidos. Cada vez que executar o %1, ele continuará a transferência onde parou anteriormente. + + + + Gridcoin + Gridcoin + + + + Error: Specified data directory "%1" cannot be created. + Erro: Diretoria de dados especificada "%1" não pode ser criada. + + + Error Erro + %n GB of free space available - - %n GB de espaço livre disponível - %n GB de espaço livre disponível - + %n GB de espaço livre disponível%n GB de espaço livre disponível%n GB de espaço livre disponível + (of %n GB needed) - - (de %n GB necessários) - (de %n GB necessários) - + (de %n GB necessários)(de %n GB necessários)(de %n GB necessários) + (%n GB needed for full chain) - - (de %n GB necessários para cadeia completa) - (de %n GB necessários para cadeia completa) - + (de %n GB necessários para cadeia completa)(de %n GB necessários para cadeia completa)(de %n GB necessários para cadeia completa) MRCModel + + You must have a mature balance of at least 1 GRC to submit an MRC. + Tem que ter um balanço com maturidade de pelo menos 1 GRC para poder submeter um pedido de MRC. + + + + Too soon since your last research rewards payment. + Muito cedo desde o último pagamento de recompensa de pesquisa. + + + + The total fee (the minimum fee + fee boost) is greater than the rewards due. + A taxa total (taxa mínima + taxa de boost) é maior que os ganhos da recompensa. + + + + Your MRC was successfully submitted earlier but has now become stale without being bound to the just received block by a staker. This may be because your MRC was submitted just before the block was staked and the MRC didn't make it to the staker in time, or your MRC was pushed down in the queue past the pay limit. Please wait for the next block to clear the queue and try again. + O seu MRC foi submetido com sucesso mais cedo, mas agora tornou-se obsoleto sem estar ligado ao bloco recém recebido por um staker. Isto pode acontecerr porque o seu MRC foi submetida pouco antes do bloco ter sido staked e o MRC não chegou a tempo ao staker, ou o seu MRC desceu na fila para além do limite de pagamentos. Por favor, aguarde pelo próximo bloco para limpar a fila de espera e tente novamente. + + + You have a pending MRC request. Tem uma solicitação de MRC pendente. + + Your MRC was successfully submitted, but other MRCs with higher fees have pushed your MRC down in the queue past the pay limit, and your MRC will be canceled. Wait until the next block is received and the queue clears and try again. Your fee for the canceled MRC will be refunded. + O seu MRC foi submetido com êxito, mas outros MRCs com taxas mais altas, fizeram o seu MRC baixar na fila, ultrapassando o limite de pagamentos, e o seu MRC será cancelado. Aguarde até que o próximo bloco seja recebido e a fila seja limpa e tente novamente. A sua taxa para o MRC cancelado será reembolsada. + + + + The MRC queue is full. You can try boosting your fee to put your MRC request in the queue and displace another MRC request. + A fila do MRC está cheia. Pode tentar aumentar a sua taxa para colocar o seu pedido MRC na fila e remover da fila outro pedido de MRC. + + + The wallet is locked. A carteira está trancada. @@ -1454,73 +1914,179 @@ Isto significa que uma taxa de pelo menos %2 é necessária. MRCRequestPage + MRC Requests Solicitações MRC + Please wait. Por favor aguarde. + MRC Fee @ Pay Limit Position in Queue Taxa MRC @ Posição Limite de Pagamento na Fila + + MRC Fee @ Tail of Queue + Taxa MRC @ Na Cauda da Fila + + + + Your projected or actual position among MRCs in the memory pool ordered by MRC fee in descending order + A sua posição projetada ou real entre os MRCs na reserva de memória, ordenada por taxa de MRC por ordem decrescente + + + Number of All MRC Requests in Queue Número de Todos os Pedidos MRC na Fila + The number of MRCs in the memory pool Número de pedidos MRC em espera + + + + + Your Projected MRC Request Position in Queue + A sua posição prevista do seu pedido MRC na fila de espera + + + + The MRC fee being paid by the MRC in the last position within the pay limit in the memory pool + A taxa de MRC que está a ser paga pelo MRC na última posição dentro do limite de remuneração na reserva de memória + + + + MRC Request Pay Limit per Block + Limite de pagamento por bloco do pedido MRC + + + + Your MRC Calculated Minimum Fee + A sua taxa mínima calculada pelo MRC + + + + The calculated minimum fee for the MRC. This may not be sufficient to submit the MRC if the queue is already full. In that case, you need to use the MRC fee boost to raise the fee to get your MRC in the queue. + A taxa mínima calculada para o MRC. Este valor pode não ser suficiente para submeter o MRC se a fila de espera já estiver cheia. Nesse caso, é necessário que faça um boost da taxa de MRC para a aumentar, colocando o MRC na fila de espera. + + + + The lowest MRC fee being paid of MRCs in the memory pool + A taxa mais baixa de MRC que está a ser paga de MRCs na reserva de memória + + + + The maximum number of MRCs that can be paid per block + O número máximo de MRCs que pode ser pago por bloco + + + + The highest MRC fee being paid of MRCs in the memory pool + A taxa mais alta de MRC que está a ser paga de MRCs na reserva de memória + + + + MRC Fee @ Head of Queue + Taxa MRC @ No Topo da Fila + + + + MRC Fee Boost + Aumento da taxa de inscrição no MRC + + + + Raise to Minimum For Submit + Subir para o Mínimo para Submeter + + + Update Atualizar + Submit Submeter + + + + + + + + + + N/A + N/A + + + + + Your Submitted MRC Request Position in Queue A Posição na Fila do Seu Pedido MRC Submetido + You must have an active beacon and the wallet must be in solo mode to submit MRCs. Tem um pedido ativo de beacon e, a carteira tem de estar em modo solo para submeter MRCs. + The block version must be v12 or higher to submit MRCs. A versão do bloco tem de ser v12 ou superior para submeter pedidos MRC. + The wallet must be in sync to submit MRCs. A carteira tem de estar sincronizada para submeter um pedido MRC. + A block update must have occurred after wallet start or sync to submit MRCs. Uma atualização do bloco tem de ocorrer depois da carteira iniciar ou sincronizar, para submeter um pedido MRC. - + + + You must have a mature balance of at least 1 GRC to submit an MRC. + Tem que ter um balanço com maturidade de pelo menos 1 GRC para poder submeter um pedido de MRC. + + NoResult + Form Formulário + + Nothing here yet... Nada aqui ainda... + No results available. Sem resultados disponíveis. + Loading... Carregando... + Privacy Enabled... Privacidade Habilitada... @@ -1528,301 +2094,480 @@ Isto significa que uma taxa de pelo menos %2 é necessária. OptionsDialog + Options Opções + &Main &Principal + &Network &Rede + Map port using &UPnP Mapear porto utilizando &UPnP + Reserved amount secures a balance in wallet that can be spendable at anytime. However reserve will secure utxo(s) of any size to respect this setting. Quantia reservada assegura um saldo na carteira que pode ser gasto a qualquer altura, No entanto, a reserva irá assegurar utxo(s) de qualquer tamanho para respeitarem estas definições. + Reser&ve Reser&var + Automatically start Gridcoin after logging in to the system. Começar Gridcoin automaticamente depois de entrar no sistema. + &Start Gridcoin on system login &Iniciar Gridcoin no arranque do sistema + Automatically open the Gridcoin client port on the router. This only works when your router supports UPnP and it is enabled. Abre a porta do cliente Gridcoin automaticamente no router. Isto apenas funciona se o seu router suportar UPnP e estiver habilitado. + Pro&xy IP: IP da Pro&xy: + IP address of the proxy (e.g. 127.0.0.1) Endereço IP da proxy (ex: 127.0.0.1) + &Port: &Porto: + Port of the proxy (e.g. 9050) Porto do proxy (ex: 9050) + Staking A realizar stake + + This enables or disables staking (the default is enabled). Note that a change to this setting will permanently override the config file with an entry in the settings file. + Isto ativa ou desativa o staking (por predefinição está ativado). Note que uma alteração a esta definição irá substituir permanentemente o ficheiro de configuração por uma entrada no ficheiro de definições. + + + Enable Staking Habilitar Realização de Stake + + This enables or disables splitting of stake outputs to optimize staking (default disabled). Note that a change to this setting will permanently override the config file with an entry in the settings file. + Isso permite ativar ou desativar a divisão das saídas de stake para otimizar a aposta (desativado por padrão). Note que uma alteração nesta configuração irá substituir permanentemente o arquivo de configuração com uma entrada no ficheiro de configurações. + + + + Enable Stake Splitting + Ativar Divisão de Stake + + + + Target Efficiency + Eficiência do Objetivo + + + + Valid values are between 75 and 98 percent. Note that a change to this setting will permanently override the config file with an entry in the settings file. + Valores válidos estão entre 75 e 98%. Note que uma alteração a esta configuração, irá sobrepor permanentemente o ficheiro de configuração com uma entrada nas definições do ficheiro. + + + + Min Post Split UTXO + Mínimo Pós-divisão UTXO + + + + Valid values are 800 or greater. Note that a change to this setting will permanently override the config file with an entry in the settings file. + Os valores válidos são 800 ou superior. Note que uma alteração a esta definição substituirá permanentemente o ficheiro de configuração por uma entrada no ficheiro de definições. + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. Minimize em vez sair da aplicação quando a janela é fechada. Com esta opção selecionada, a aplicação apenas será encerrada quando escolher Sair da aplicação no menu. + &Confirm on close &Confirmar ao sair + Disable Transaction Notifications Desabilitar Notificações de Transações + Disable Poll Notifications - Desabilitar Notificações de Votações + Desabilitar Notificações de Sondagens + The user interface language can be set here. This setting will take effect after restarting Gridcoin. O idioma da interface de utilizador pode ser definido aqui. Estas definições farão efeito assim que reiniciar o Gridcoin. + Style: Tema: + Choose a stylesheet to change the look of the wallet. Escolha um tema para modificar o aspeto da sua carteira. + Whether to show Gridcoin addresses in the transaction list or not. Mostrar ou não endereços de Gridcoin na lista de transações. + &Display addresses in transaction list &Mostrar endereços na lista de transações + &Window &Janela + &Apply &Aplicar + Show only a tray icon after minimizing the window. Apenas mostrar o ícone na área de notificação após minimizar a janela. + Start minimized Iniciar minimizado + Allow regular checks for updates Permitir verificações regulares por atualizações + Disable &update checks Desabilitar verificações de &atualização + + Return change to an input address for contract transactions + Devolver o troco para um endereço de entrada para transações de contrato + + + + Connect to the Gridcoin network through a SOCKS5 proxy (e.g. when connecting through Tor). + Ligar à rede Gridcoin através de um proxy SOCKS5 (por exemplo, quando a ligação é feita através do Tor). + + + &Connect through SOCKS5 proxy: &Ligar através de proxy SOCKS5: + &Minimize to the tray instead of the taskbar &Minimizar para a área de notificação e não para a barra de ferramentas + M&inimize on close M&inimizar ao fechar + &Display &Visualização + User Interface &language: &Idioma da interface de utilizador: + &Unit to show amounts in: &Unidade para mostrar quantias: + Choose the default subdivision unit to show in the interface and when sending coins. Escolha a unidade da subdivisão predefinida para ser mostrada na interface e quando enviar as moedas. + Only display transactions on or after Mostrar transações apenas durante ou depois + Setting this will cause the transaction table to only display transactions created on or after this date. Estas definições irão fazer com que a tabela de transações mostre apenas, transações durante ou depois desta data. + + &OK + &OK + + + &Cancel &Cancelar + default por defeito + Dark Escuro + Light Claro + + Warning Aviso + + This setting will take effect after restarting Gridcoin. Estas definições entrarão em efeito depois de reiniciar o Gridcoin. + The supplied proxy address is invalid. O endereço de proxy introduzido é inválido. - + + + The supplied target staking efficiency is invalid. + A eficiência de staking do alvo fornecido é inválida. + + + + The supplied minimum post stake-split UTXO size is invalid. + O tamanho mínimo de UTXO pós-divisão de stack fornecido é inválido. + + OverviewPage + Form Formulário + Available: Disponível: + Your current spendable balance O seu saldo disponível atual + Immature: Imatura: + Wallet Carteira + + The displayed information may be out of date. Your wallet automatically synchronizes with the Gridcoin network after a connection is established, but this process has not completed yet. A informação mostrada pode estar desatualizada. A sua carteira sincroniza automaticamente com a rede Gridcoin depois da ligação ser estabelecida, mas este processo ainda não está completo. + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance Total de transações que têm de ser ainda confirmadas, e ainda não contam para o balanço atual + + Total: + Total: + + + Coin Weight: Peso da Moeda: + Pending Reward: Recompensas Pendentes: + Open the researcher/beacon configuration wizard. Abrir o assistente de configuração do investigador/beacon + Action Needed Ação Necessária + Total mined coins that have not yet matured. Total de moedas mineradas que ainda não estão maduras. + Immature Stake: Stake Imatura: + Amount staked for a recent block that must wait for 110 confirmations to mature before you can spend it. Quantia realizada em stake num bloco recente, que tem de esperar por 110 confirmações antes de poder ser gasta. + Account Overview Visão Geral da Conta + + CPID + CPID + + + + + 0.00 + 0.00 + + + + Magnitude + Magnitude + + + Available (GRC) Disponível (GRC) + Unconfirmed: Não confirmada: + Your current total balance O seu saldo total atual + Staking A realizar stake: + Blocks: Blocos: + Difficulty: Dificuldade: + Net Weight: Peso da Rede: + Researcher Investigador + + Open the Manual Reward Claim (MRC) request page + Abrir a página de pedido de Pedido de Recompensa Manual (MRC) + + + + Magnitude: + Magnitude: + + + Status: Estado: + + You are approaching the accrual limit of 16384 GRC. If you have a relatively low balance, you should request payment via MRC so that you do not lose earned rewards. + Está a atingir o limite de acumulação de 16384 GRC. Se tiver um saldo relativamente baixo, deve solicitar o pagamento através de MRC para que não perca as recompensas ganhas. + + + Recent Transactions Transações Recentes + Current Polls - Votações Atuais + Sondagens Atuais + + Out of Sync Fora de Sincronia + + Pool + Pool + + + Staking Only A Realizar Stake Apenas @@ -1830,22 +2575,32 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PeerTableModel + Node ID ID do Nódulo + Node/Service Nódulo/Serviço + + Ping + Ping + + + Sent Enviado + Received Recebido + User Agent Agente do Utilizador @@ -1853,50 +2608,93 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollCard + Form Formulário + Votes: Votos: + Expiration: Data de Término: + Top Answer: Resposta Mais Votada: + Total Weight: Peso Total: + Poll Type - Tipo de Votação + Tipo de Sonadagem + + + + % of AVW: + %s do AVW + + + + AVW: + AVW: + + + + Your Last Vote: + O Seu Último Voto: + + + + Your Vote Weight: + O Peso do Seu Voto: + + Your % of AVW: + A Sua % de AVW + + + Balance Balanço + + Magnitude + Magnitude + + + Validated Validado + Invalid Inválido + + Voting finished. Votação terminada. + Vote Voto + Details Detalhes @@ -1904,6 +2702,7 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollCardView + Form Formulário @@ -1911,14 +2710,17 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollDetails + Form Formulário + Additional Fields Campos Adicionais + Top Answer: Resposta Mais Votada: @@ -1926,10 +2728,12 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollResultChoiceItem + Form Formulário + Weight: Peso: @@ -1937,33 +2741,40 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollResultDialog + Poll Details - Detalhes da Votação + Detalhes da Sondagem + Poll ID - ID da Votação + ID da Sondagem PollTab + Form Formulário - Press "Refresh" to update the list. - Clique em "Recarregar " para atualizar a lista. + + Press "Refresh" to update the list. + Clique em "Recarregar " para atualizar a lista. + This may take several minutes. Isto pode demorar alguns minutos. + Show Results Mostrar Resultados + Vote Voto @@ -1971,42 +2782,52 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollTableDataModel + Title Título + Poll Type - Tipo de Votação + Tipo de Sondagem + Duration Duração + Expiration Data de Término + Weight Type Tipo de Peso + Votes Votos + Total Weight Peso Total + % of Active Vote Weight % Peso dos Votos Ativos + Validated Validado + Top Answer Resposta Mais Votada @@ -2014,128 +2835,159 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollWizard + Create a Poll - Criar uma Votação + Criar uma Sondagem PollWizardDetailsPage + Poll Details - Detalhes da Votação + Detalhes da Sondagem + Some fields are locked for the selected poll type. - Alguns campos estão bloqueados para o tipo de votação selecionada. + Alguns campos estão bloqueados para o tipo de sondagem selecionada. + Poll Type: - Tipo de Votação: + Tipo de Sondagem: + Duration: Duração: + days dias + Title: Título: + Question: Questão: + Discussion URL: URL de Discussão: + A link to the main discussion thread on GitHub or Reddit. Link para a discussão principal no GitHub ou no Reddit. + Weight Type: Tipo de Peso: + Response Type: Tipo de Resposta: + Choices: Escolhas: + A poll with a yes/no/abstain response type cannot include any additional custom choices. - Uma votação com uma resposta do tipo sim/não/abster-se, não pode incluir quaisquer escolhas adicionais. + Uma sondagem com uma resposta do tipo sim/não/abster-se, não pode incluir quaisquer escolhas adicionais. + Additional Fields: Campos Adicionais: + + Create Poll - Criar Votação + Criar Sondagem + Balance Balanço + Magnitude+Balance Magnitude+Balanço + Yes/No/Abstain Sim/Não/Abster-se + Single Choice Escolha Única + Multiple Choice Escolha Múltipla + This poll will cost %1 plus a transaction fee. Continue? - Esta votação irá custar %1 para além duma taxa adicional. Continuar? + Esta sondagem irá custar %1 para além duma taxa adicional. Continuar? PollWizardProjectPage + Project Listing Proposal Proposta da Listagem de Projetos + Add an unlisted project Adicionar um projeto não listado + Remove a listed project Remover um projeto listado + Proposals must follow community guidelines for validation. Please review the wiki and verify that the prerequisites have been fulfilled: As propostas devem seguir as diretrizes da comunidade, para que sejam validadas. Por favor reveja a wiki e verifique que os pré requisitos foram preenchidos: + Project Name: Nome do Projeto: + This project satisfies the Gridcoin listing criteria. Este projeto satisfaz a listagem de critérios do Gridcoin. + Project URL URL do Projeto + Choose a project to delist: Escolha um projeto para retirar: @@ -2143,14 +2995,17 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollWizardSummaryPage + Poll Created - Votação Criada + Sondagem Criada + The poll will activate with the next block. - A votação será ativada no próximo bloco. + A sondagem será ativada no próximo bloco. + Copy ID Copiar ID @@ -2158,118 +3013,193 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollWizardTypePage + Create a Poll - Criar uma Votação + Criar uma Sondagem + The Gridcoin community established guidelines for polls with requirements for each type. Please read the wiki for more information: - A comunidade Gridcoin estabeleceu diretrizes para as votações, com requisitos para cada tipo. Por favor leia a wiki para mais informações: + A comunidade Gridcoin estabeleceu diretrizes para as sondagem, com requisitos para cada tipo. Por favor leia a wiki para mais informações: + Choose a poll type: - Escolha o tipo de votação: + Escolha o tipo de sondagem: ProjectTableModel + Name Nome + Eligible Elegível + Whitelist Lista Aprovada + Has GDPR Controls Tem Controles GDPR + + Magnitude + Magnitude + + + Avg. Credit Média de Créditos - + + + CPID + CPID + + QObject - Error: Specified data directory "%1" does not exist. + + Error: Cannot parse command line arguments. Please check the arguments and ensure they are valid and formatted correctly: + + + Erro: Não é possível analisar os argumentos na linha de comando. Verifique os argumentos e certifique-se de que são válidos e estão formatados corretamente: + + + + + Error: Cannot read configuration file. Please check the path and format of the file. + Erro: Não é possível ler o ficheiro de configuração. Verifique o caminho e o formato do ficheiro. + + + + Error: Specified data directory "%1" does not exist. Erro: A diretoria %1 especificada não existe. + Error: Cannot obtain a lock on the specified data directory. An instance is probably already using that directory. Erro: Não foi possível cadear a diretoria de dados especificada. Uma instância já está provavelmente a utilizar essa diretoria + Error: Cannot parse configuration file: %1. Erro: Não foi possível analisar o ficheiro de configuração: %1. + Error initializing settings: %1 Erro ao inicializar as definições: %1 - %1 didn't yet exit safely... + + %1 didn't yet exit safely... %1 ainda não saiu de modo seguro... + N/A N/D + + + %1 ms + %1 ms + + + + + %1 s + %1 s + + %n second(s) - - %n segundo(s) - %n segundo(s) - + %n segundo(s)%n segundo(s)%n segundo(s) + %n minute(s) - - %n minuto(s) - %n minuto(s) - + %n minuto(s)%n minuto(s)%n minuto(s) + %n hour(s) - - %n hora(s) - %n hora(s) - + %n hora(s)%n hora(s)%n hora(s) + %n day(s) - - %n dia(s) - %n dia(s) - + %n dia(s)%n dia(s)%n dia(s) + + %n week(s) - - %n semana(s) - %n semana(s) - + %n semana(s)%n semana(s)%n semana(s) + %1 and %2 %1 e %2 + %n year(s) - - %n ano(s) - %n ano(s) - + %n ano(s)%n ano(s)%n ano(s) + + + + %1 B + %1 B + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + %1 d + %1 d + + + + %1 h + %1 h + + + + %1 m + %1 m + None Nenhum + %1 remaining. %1 restante. @@ -2277,46 +3207,57 @@ Isto significa que uma taxa de pelo menos %2 é necessária. QRCodeDialog + QR Code Dialog Diálogo de Código QR + Request Payment Solicitar Pagamento + Label: Etiqueta: + Message: Mensagem: + Amount: Quantia: + &Save As... &Guardar Como... + Error encoding URI into QR Code. Erro ao codificar URI para Código QR. + The entered amount is invalid, please check. A quantia introduzida é inválida, por favor verifique. + Resulting URI too long, try to reduce the text for label / message. Resultado do URI demasiado longo, tente reduzir o texto para a etiqueta / mensagem. + Save QR Code Guardar Código QR + PNG Image Name of PNG file format Imagem PNG @@ -2325,278 +3266,433 @@ Isto significa que uma taxa de pelo menos %2 é necessária. RPCConsole + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + N/A N/D + Client version Versão do cliente + &Information &Informação + Startup time Hora de Inicialização + Number of connections Número de ligações + Block chain Blockchain + Current number of blocks Número atual de blocos + Qt version Versão Qt + Difficulty Dificuldade + Last block time Data do último bloco + &Open &Abrir + &Clear &Limpar + + &Peers + &Peers + + + Banned peers Peers banidos + + Select a peer to view detailed information. Selecione um peer para visualizar a informação detalhada + Whitelisted Na Lista Aprovada + Direction Direção + Version Versão + User Agent Agente do Utilizador + Services Serviços + Starting Block Bloco Inicial + Synced Headers Cabeçalhos Sincronizados + Synced Blocks Blocos Sincronizados + Ban Score Resultado do Ban + Connection Time Tempo de Conexão + Last Send Último Enviado + Last Receive Último Recebido + Sent Enviado + Received Recebido + Ping Time Tempo de Ping + The duration of a currently outstanding ping. A duração de pings excecionais actuais. + Ping Wait Espera de Ping + Min Ping Ping Mínimo + Time Offset Diferença Tempo + &Console &Consola + + &Scraper + &Scraper + + + &Network Traffic &Tráfego de Rede + Totals Totais + In: Entrada: + Out: Saída: + Debug log file Ficheiro de registo de depuração + Clear console Limpar consola + Gridcoin - Debug Console Gridcoin - Consola de Depuração + Boost version Versão de Boost + Gridcoin Core: Núcleo Gridcoin: + Network: Rede: + On testnet Na rede de testes + Estimated total blocks Total estimado de blocos + Open the Gridcoin debug log file from the current data directory. This can take a few seconds for large log files. Abre o ficheiro de registo de depuração do Gridcoin na directoria atual. Isto pode levar alguns segundos para ficheiros de registo maiores. + Command-line options Opções da linha de comandos + Show the Gridcoin help message to get a list with possible Gridcoin command-line options. Mostra a mensagem de ajuda do Gridcoin para obter uma lista com possíveis opções da linha de comandos. + &Show &Mostrar + OpenSSL version Versão OpenSSL + Client name Nome do cliente + &Disconnect &Desligar + + + + Ban for Banir por + 1 &hour 1 &hora + 1 &day 1 &dia + 1 &week 1 &semana + 1 &year 1 &ano + &Unban &Desbloquear + Yes Sim + No Não + Welcome to the Gridcoin RPC console! Bem-vindo à consola RPC Gridcoin! + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Use as setas para cima e para baixo para navegar no histórico e, <b>Ctrl-L</b> para limpar o ecrã. + Type <b>help</b> for an overview of available commands. Escreva <b>help</b> para visualizar os comandos disponíveis. + + %1 B + %1 B + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + %1 m + %1 m + + + + %1 h + %1 h + + + + %1 h %2 m + %1 h %2 m + + + (node id: %1) (id do nó: %1) + + via %1 + via %1 + + + + never nunca + Inbound Entrada + Outbound Saída + + Unknown Desconhecido @@ -2604,10 +3700,13 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ReceiveCoinsPage + + Receive Payment Receber Pagamento + Search by address or label Pesquisar por endereço ou etiqueta @@ -2615,73 +3714,96 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherModel + Beacon is active. Beacon está ativo. + Balance too low to send a beacon contract. Balanço muito baixo para enviar um contrato de beacon. + Beacon private key missing or invalid. Chave privada do Beacon inválida ou perdida. + Current beacon is not renewable yet. Beacon atual não é possível de ser já renovado. + Unable to send beacon transaction. See debug.log Impossível enviar a transação do beacon. Ver debug.log + Unlock wallet fully to send a beacon transaction. Desbloquear completamente a carteira para enviar uma transação do beacon. + No active beacon. Sem beacon ativo. + No CPID detected. CPID não detetado. + Zero magnitude in the last superblock. Magnitude zero no último super bloco. + Pending beacon is awaiting network confirmation. Beacon pendente a aguardar confirmação da rede. + Beacon expires soon. Renew immediately. Beacon expira brevemente. Renove-o imediatamente. + Beacon eligible for renewal. Beacon elegível para renovação. + + Waiting for sync... Aguardando pela sincronização... + Not whitelisted Não listado na lista aprovada + Not attached Não anexado - + + + Uses external adapter + Utiliza adaptador externo + + ResearcherWizard + Researcher Configuration Configuração de Investigador + &Start Over &Recomeçar @@ -2689,66 +3811,82 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardAuthPage + + Beacon Verification Verificação do Beacon + Gridcoin needs to verify your BOINC account CPID. Please follow the instructions below to change your BOINC account username. The network needs 24 to 48 hours to verify a new CPID. Gridcoin necessita de verificar o CPID da sua conta BOINC. Por favor, siga as instruções abaixo para modificar o seu nome de utilizador do BOINC. A rede necessita de 24 a 48 horas para verificar um novo CPID. + 1. Sign in to your account at the website for a whitelisted BOINC project. - 1. Entre na sua conta num website dum projeto BOINC na lista aprovada. + 1. Entre na sua conta no sítio web dum projeto BOINC que esteja na lista aprovada. - 2. Visit the settings page to change your username. Many projects label it as "other account info". - 2. Visite a página de configurações para alterar o nome de utilizador. Muitos projetos identificam como "outra informação da conta" + + 2. Visit the settings page to change your username. Many projects label it as "other account info". + 2. Visite a página de configurações para alterar o nome de utilizador. Muitos projetos identificam como "outra informação da conta" + + 3. Change your "name" (real name or nickname) to the following verification code: + 3. Altere o seu "nome" (nome real ou alcunha) para o seguinte código de verificação: + + + Copy the verification code to the system clipboard Copie o código de verificação para a área de transferência + &Copy &Copiar - 4. Some projects will not export your statistics by default. If available, enable the privacy setting that gives consent to the project to export your statistics data. Many projects place this setting on the "Preferences for this Project" page and label it as "Do you consent to exporting your data to BOINC statistics aggregation web sites?" - 4. Alguns projetos não irão exportar as suas estatísticas por defeito. Se a opção estiver disponível, deve alterar as definições de privacidade que consentem que um projeto possa exportar os dados das suas estatísticas. Muitos projetos colocam esta definição na página "Preferências para este Projeto" e etiquetam-na como "Pretende consentir a exportação dos seus dados para websites de estatísticas de agregação do BOINC ?" + + 4. Some projects will not export your statistics by default. If available, enable the privacy setting that gives consent to the project to export your statistics data. Many projects place this setting on the "Preferences for this Project" page and label it as "Do you consent to exporting your data to BOINC statistics aggregation web sites?" + 4. Alguns projetos não irão exportar as suas estatísticas por defeito. Se a opção estiver disponível, deve alterar as definições de privacidade que consentem que um projeto possa exportar os dados das suas estatísticas. Muitos projetos colocam esta definição na página "Preferências para este Projeto" e etiquetam-na como "Pretende consentir a exportação dos seus dados para sítios web de estatísticas de agregação do BOINC ?" - 5. Wait 24 to 48 hours for the verification process to finish (beacon status will change to "active"). - 5. Aguarde 24 a 48 horas para o processo de verificação terminar (o estado do beacon irá passar a "ativo") + + 5. Wait 24 to 48 hours for the verification process to finish (beacon status will change to "active"). + 5. Aguarde 24 a 48 horas para o processo de verificação terminar (o estado do beacon irá passar a "ativo") + 6. After that, you may change the username back to your preference. 6. Depois disso, pode voltar a alterar o seu nome de utilizador de acordo com as suas preferências. + <html> <head/> <body> -<h4 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> -<span style=" font-size:medium; font-weight:600;">Remember:</span> +<h4 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> +<span style=" font-size:medium; font-weight:600;">Remember:</span> </h4> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 0;"> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The network only needs to verify the code above at a single whitelisted BOINC project even when you participate in multiple projects. </li> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The verification code expires after three days pass. </li> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A beacon expires after six months pass. </li><li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A beacon becomes eligible for renewal after five months pass. The wallet will remind you to renew the beacon. </li> -<li style=" margin-top:6px; margin-bottom:12px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You will not need to change your username again to renew a beacon unless it expires. </li> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 0;"> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The network only needs to verify the code above at a single whitelisted BOINC project even when you participate in multiple projects. </li> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The verification code expires after three days pass. </li> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A beacon expires after six months pass. </li><li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A beacon becomes eligible for renewal after five months pass. The wallet will remind you to renew the beacon. </li> +<li style=" margin-top:6px; margin-bottom:12px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You will not need to change your username again to renew a beacon unless it expires. </li> </ul> </body> </html> <html> <head/> <body> -<h4 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> -<span style=" font-size:medium; font-weight:600;">Lembre-se</span> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 0;"> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A rede apenas necessita que verifique o código acima num projeto BOINC que esteja na lista aprovada, mesmo que participe em múltiplos projetos. </li> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O código de verificação expira após 3 dias. </li> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O beacon expira após 6 meses</li><li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O beacon torna-se elegível para renovação após passarem 5 meses. A carteira irá relembrá-lo para renovar o beacon. </li> -<li style=" margin-top:6px; margin-bottom:12px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Não necessita de mudar o seu nome de utilizador novamente depois de renovar o beacon, a não ser que o deixe expirar. </li> +<h4 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> +<span style=" font-size:medium; font-weight:600;">Lembre-se</span> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 0;"> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A rede apenas necessita que verifique o código acima num projeto BOINC que esteja na lista aprovada, mesmo que participe em múltiplos projetos. </li> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O código de verificação expira após 3 dias. </li> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O beacon expira após 6 meses</li><li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O beacon torna-se elegível para renovação após passarem 5 meses. A carteira irá relembrá-lo para renovar o beacon. </li> +<li style=" margin-top:6px; margin-bottom:12px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Não necessita de mudar o seu nome de utilizador novamente depois de renovar o beacon, a não ser que o deixe expirar. </li> </ul> </body> </html> @@ -2757,37 +3895,47 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardBeaconPage + + Beacon Advertisement Anúncio do Beacon + A beacon links your BOINC accounts to your wallet. After sending a beacon, the network tracks your BOINC statistics to calculate research rewards. Um beacon linka a sua conta de BOINC à sua carteira. Depois de enviar o beacon, a rede monitoriza as suas estatísticas do BOINC para calcular as recompensas de investigação. + &Advertise Beacon &Anunciar Beacon - Press "Next" to continue. - Carregue em "Seguinte" para continuar. + + Press "Next" to continue. + Carregue em "Seguinte" para continuar. ResearcherWizardEmailPage + + BOINC Email Address Endereço de Email do BOINC + Enter the email address that you use for your BOINC project accounts. Gridcoin uses this email address to find BOINC projects on your computer. Insira o endereço de email que utiliza nos projetos do BOINC. O Gridcoin utiliza esse email para encontrar os projetos do BOINC no seu computador. + Email Address: Endereço de Email: + The wallet will never transmit your email address. A carteira nunca irá transmitir o seu endereço de email. @@ -2795,87 +3943,115 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardInvestorPage + Summary Sumário + Investor Mode Modo de Investidor + You opted out of research rewards and will earn staking rewards only. Optou por não receber recompensas de investigação, e irá ganhar apenas as recompensas de realizar stake apenas. - Press "Start Over" if you want to switch modes. - Carregue em "Recomeçar" se quiser mudar de modo. + + Press "Start Over" if you want to switch modes. + Carregue em "Recomeçar" se quiser mudar de modo. ResearcherWizardModeDetailPage + Select Researcher Mode Selecione Modo de Investigador + How can I participate? Como posso participar? + <html> <head/> <body> -<p>You can participate as either a miner or investor. <span style=" font-weight:600;">Miners</span> earn Gridcoin by participating in whitelisted BOINC projects. To redeem their rewards, miners must stake blocks. <span style=" font-weight:600;">Solo Miners</span> stake blocks on their own which typically requires a balance of at least 5000 GRC. <span style=" font-weight:600;">Pool Miners</span> avoid this upfront investment by letting a third party (the pool) stake blocks on their behalf. Pool mining is recommended for new users with a low initial balance. <span style=" font-weight:600;">Investors</span> own Gridcoin but do not participate in BOINC mining. By using their balance to stake blocks, investors help to secure the network and are rewarded 10 GRC per block.</p> +<p>You can participate as either a miner or investor. <span style=" font-weight:600;">Miners</span> earn Gridcoin by participating in whitelisted BOINC projects. To redeem their rewards, miners must stake blocks. <span style=" font-weight:600;">Solo Miners</span> stake blocks on their own which typically requires a balance of at least 5000 GRC. <span style=" font-weight:600;">Pool Miners</span> avoid this upfront investment by letting a third party (the pool) stake blocks on their behalf. Pool mining is recommended for new users with a low initial balance. <span style=" font-weight:600;">Investors</span> own Gridcoin but do not participate in BOINC mining. By using their balance to stake blocks, investors help to secure the network and are rewarded 10 GRC per block.</p> </body> </html> <html> <head/> <body> -<p>Pode participar como minerador ou investidor. <span style=" font-weight:600;">Mineradores</span> ganham Gridcoins ao participar em projectos BOINC na lista aprovada. Para ganharem as suas recompensar, os mineradores têm de realizar stake em blocos. <span style=" font-weight:600;">Mineradores a solo</span> realizam stake em blocos por sua conta, o que tipicamente requer um balanço inicial de pelo menos 5000 GRC. <span style=" font-weight:600;">Mineradores de Pool</span> evitam este investimento inicial ao deixar que uma terceira parte (a pool) realize o stake de blocos em seu nome. Mineração em Pool é recomendado para novos utilizadores que têm um balanço inicial baixo. <span style=" font-weight:600;">Investidores</span> têm o Gridcoin mas não participam na Mineração do BOINC. Ao utilizar o seu balanço para realizar stake de blocos, os investidor ajudam a garantir a segurança da rede e são recompensados com 10 GRC por bloco. </p> +<p>Pode participar como minerador ou investidor. <span style=" font-weight:600;">Mineradores</span> ganham Gridcoins ao participar em projectos BOINC na lista aprovada. Para ganharem as suas recompensar, os mineradores têm de realizar stake em blocos. <span style=" font-weight:600;">Mineradores a solo</span> realizam stake em blocos por sua conta, o que tipicamente requer um balanço inicial de pelo menos 5000 GRC. <span style=" font-weight:600;">Mineradores de Pool</span> evitam este investimento inicial ao deixar que uma terceira parte (a pool) realize o stake de blocos em seu nome. Mineração em Pool é recomendado para novos utilizadores que têm um balanço inicial baixo. <span style=" font-weight:600;">Investidores</span> têm o Gridcoin mas não participam na Mineração do BOINC. Ao utilizar o seu balanço para realizar stake de blocos, os investidor ajudam a garantir a segurança da rede e são recompensados com 10 GRC por bloco. </p> </body> </html> + Earn 10 GRC Block Reward Ganhe 10 GRC por recompensa por bloco + Ability to Vote Capacidade para Votar + Decentralized Descentralizada + Helps Secure Network Ajuda a Segurança da Rede + Keep 100% of Rewards Mantenha 100% das Recompensas + Earn BOINC Rewards Ganhe Recompensas do BOINC + No Upfront Investment Sem investimento Inicial + My Choice: Minha Escolha: + BOINC Leaderboards Tabelas de Classificação do BOINC + + Pool + Pool + + + + Solo + Solo + + + Investor Investidor + Pool Only Pool Apenas @@ -2883,18 +4059,32 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardModePage + Select Researcher Mode Selecione Modo de Investigador + How would you like to participate? Como gostaria de participar? + + Solo + Solo + + + + Pool + Pool + + + Investor Investidor + Help me choose... Ajude-me a escolher... @@ -2902,81 +4092,115 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardPoolPage + Summary Sumário + Pool Mode Modo de Mineração por Pool - In this mode, a pool will take care of staking research rewards for you. Your wallet can still earn standard staking rewards on your balance. You do not need a BOINC account, CPID, or beacon. Please choose a pool and follow the instructions on the website to sign up and connect the pool's account manager to BOINC: - Neste modo, a pool irá tomar conta de realizar o stake para pesquisar recompensas para si. A sua carteira pode ainda ganhar recompensas normais por realizar stake. Não precisa de uma conta BOINC, CPID ou Beacon. Por favor escolha uma pool e siga as instruções no website para se registar e ligar a uma conta duma pool gestora do BOINC. + + In this mode, a pool will take care of staking research rewards for you. Your wallet can still earn standard staking rewards on your balance. You do not need a BOINC account, CPID, or beacon. Please choose a pool and follow the instructions on the website to sign up and connect the pool's account manager to BOINC: + Neste modo, a pool irá tomar conta de realizar o stake para pesquisar recompensas para si. A sua carteira pode ainda ganhar recompensas normais por realizar stake. Não precisa de uma conta BOINC, CPID ou Beacon. Por favor escolha uma pool e siga as instruções no sítio web para se registar e ligar a uma conta duma pool gestora do BOINC: + + grcpool + grcpool + + + + Arikado Pool + Arikado Pool + + + Website URL - URL do Website + URL do Sítio Web + As you sign up, the pool may ask for a payment address to send earnings to. Press the button below to generate an address. Ao registar-se, a pool pode-lhe pedir um endereço para receber os pagamentos. Carregue no botão abaixo para gerar um endereço. + New &Address Novo &Enderenço + &Copy &Copiar - Press "Next" when you are done. - Carregue em "Seguinte" quando estiver pronto. + + Press "Next" when you are done. + Carregue em "Seguinte" quando estiver pronto. + Address Label Etiqueta do Endereço + Label: Etiqueta: + Pool Receiving Address Endereço de Receção da Pool - + + + Error: failed to generate a new address. + Erro: falhou ao gerar um novo endereço. + + ResearcherWizardPoolSummaryPage + BOINC CPID Detection Deteção do CPID do BOINC + Pool Mode Modo de Mineração por Pool + BOINC Folder: Diretoria do BOINC: + Pool Status: Estado da Pool: + Re-scan the BOINC projects on your computer. Reexamine os projetos BOINC no seu computador. + &Refresh &Atualizar + Pool projects detected Projetos da pool detetados + No pool projects detected Sem projetos da Pool detetados @@ -2984,34 +4208,43 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardProjectsPage + + BOINC CPID Detection Deteção do CPID do BOINC + Gridcoin scans the BOINC projects on your computer to find an eligible cross-project identifier (CPID). The network tracks CPIDs to allocate research rewards. O Gridcoin procura os os projetos BOINC no seu computador para encontrar um identificador de cruzamento de projetos (CPID). A rede pesquisa esse CPID para distribuir as recompensas de investigação. + Email Address: Endereço de Email: + BOINC Folder: Diretoria do BOINC: + Selected CPID: CPID Selecionado: + Re-scan the BOINC projects on your computer. Reexaminar os projetos BOINC no seu computador. + &Refresh &Atualizar + An error occurred while saving the email address to the configuration file. Please see debug.log for details. Ocorreu um erro ao guardar o endereço de email para o ficheiro de configuração. Por favor veja o debug.log para detalhes. @@ -3019,82 +4252,123 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardSummaryPage + Researcher Summary Sumário de Investigação + S&ummary S&umário + + Everything looks good. Tudo parece bem. + Review Beacon Verification Rever Verificação do Beacon + Status: Estado: + + Magnitude: + Magnitude: + + + Pending Reward: Recompensas Pendentes: + + Beacon: + Beacon: + + + Age: Idade: + Expires: Expira: + Address: Endereço: + &Renew &Renovar + &Projects &Projetos + Email Address: Endereço de Email: + BOINC Folder: Diretoria do BOINC: + Selected CPID: CPID Selecionado: + Re-scan the BOINC projects on your computer. Reexaminar os projetos BOINC no seu computador. + &Refresh &Atualizar + Waiting for sync... Aguardando pela sincronização... + Beacon awaiting confirmation. Beacon a aguardar confirmação. + Beacon renewal available. Renovação do beacon disponível. + + Split CPID or mismatched email. + CPID dividido ou eMail não correspondente. + + + + Your projects either refer to more than one CPID or your projects' email do not match what you used to configure Gridcoin here. Please ensure all of your projects are attached using the same email address, the email address matches what was configured here, and if you added a project recently, update that project and then all other projects using the update button in the BOINC manager, then restart the client and recheck. + Os seus projetos referem-se a mais do que um CPID ou, o e-mail dos seus projetos não corresponde ao que utilizou para configurar o Gridcoin. Por favor, certifique-se de que todos os seus projetos estão anexados utilizando o mesmo endereço de e-mail, o que corresponde ao que foi configurado aqui, e se adicionou um projeto recentemente, atualize esse projeto de seguida, todos os outros projetos utilizando o botão de atualização no Gestor BOINC. Por último, reinicie o cliente e verifique novamente. + + + Waiting for magnitude. Aguardando pela magnitude @@ -3102,186 +4376,272 @@ Isto significa que uma taxa de pelo menos %2 é necessária. SendCoinsDialog + + + + + + + + Send Coins Enviar Moedas + Send Payment Enviar Pagamento + + 0.00 + 0.00 + + + + + Available (%1) Disponível (%1) + Coin Control Features (Advanced) Funcionalidades de Controlo de Moedas (Avançada) + + Inactive Inativo + Inputs... Entradas... + automatically selected selecionadas automaticamente + Insufficient funds! Fundos insuficientes! + Reset Repor + + Consolidate Wizard + Assistente de Consolidação + + + Quantity: Quantidade: + + + 0 + 0 + + + + Bytes: + Bytes: + + + Amount: Quantia: + + + + + 0.00 GRC + 0.00 GRC + + + Fee: Taxa: + Low Output: Produção Baixa: + no não + After Fee: Depois da taxa: + Change Modificar + custom change address alteração personalizada de endereço + Remove all transaction fields Remover todas os campos de transações + Send to multiple recipients at once Enviar para múltiplos destinatários de uma vez + Add &Recipient Adicionar &Destinatário + Clear &All Limpar &Tudo + Confirm the send action Confirme ação de envio + S&end E&nviar + Enter a Gridcoin address (e.g. S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) Insira um endereço Gridcoin (ex: S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) + Copy quantity Copiar quantidade + Copy amount Copiar quantia + Copy fee Copiar taxa + Copy after fee Copiar depois da taxa + Copy bytes Copiar bytes + Copy low output Copiar baixa produção + Copy change Copiar modificação + <b>%1</b> to %2 (%3) <b>%1</b> a %2 (%3) + Confirm send coins Confirme envio de moedas + Are you sure you want to send %1? Tem a certeza que quer enviar %1? + and e + The recipient address is not valid, please recheck. O endereço de destino não é válido, por favor verifique. + The amount to pay must be larger than 0. A quantia a pagar deverá ser maior que 0. + The amount exceeds your balance. A quantia excede o seu saldo. + The total exceeds your balance when the %1 transaction fee is included. O total excede o seu saldo quando a taxa de transação %1 está incluída. + Duplicate address found, can only send to each address once per send operation. Endereço duplicado encontrado, apenas poderá enviar uma vez por endereço, por cada operação de envio. + Error: Transaction creation failed. Erro: Criação da transação falhou. + Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. Erro: A transação foi rejeitada. Isso pode acontecer se algumas das suas moedas na carteira já tiverem sido gastas, se tiver utilizado uma cópia da wallet.dat e as moedas não tiverem sido marcadas como gastas aqui. + + (no label) (sem etiqueta) + WARNING: Invalid Gridcoin address AVISO: Endereço Gridcoin inválido + WARNING: unknown change address AVISO: endereço desconhecido + Active Ativo @@ -3289,50 +4649,73 @@ Isto significa que uma taxa de pelo menos %2 é necessária. SendCoinsEntry + A&mount: Q&antia: + Pay &To: Pagar &a: + Message: Mensagem: + &Label: &Etiqueta: + Form Formulário + The address to send the payment to (e.g. Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) O endereço para enviar o pagamento a (ex: Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) + + Alt+A + Alt+A + + + Paste address from clipboard Cole endereço da área de transferência + Send Custom Message to a Gridcoin Recipient Enviar Mensagem Personalizada a um Destinatário Gridcoin + Choose address from address book Escolha endereço do livro de endereços + + Alt+P + Alt+P + + + Remove this recipient Remover este destinatário + + Enter a label for this address to add it to your address book Escreva uma etiqueta a endereço para o adicionar ao seu livro de endereços + Enter a Gridcoin address (e.g. S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) Insira um endereço Gridcoin (ex: S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) @@ -3340,130 +4723,183 @@ Isto significa que uma taxa de pelo menos %2 é necessária. SignVerifyMessageDialog + Signatures - Sign / Verify a Message Assinaturas - Assinar / Verificar uma Mensagem + &Sign Message &Assinar Mensagem + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. Pode assinar mensagens com os seus endereços para provar que são seus. Tenha atenção para não assinar mensagens vagas, pois ataques de phishing podem tentar enganá-lo, de modo a assinar a sua identidade para os atacantes. Assine apenas declarações completamente detalhadas com as quais concorde. + The address to sign the message with (e.g. Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) O endereço para assinar a mensagem com (ex: Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) + + Choose an address from the address book Escolha um endereço do livro de endereços + + + Alt+A + Alt+A + + + Paste address from clipboard Colar endereço da área de transferência + + Alt+P + Alt+P + + + Enter the message you want to sign here Escreva aqui a mensagem que deseja assinar + Copy the current signature to the system clipboard Copiar a assinatura atual para a área de transferência + Sign the message to prove you own this Gridcoin address Assinar a mensagem para provar que possui este endereço de Gridcoin + Sign &Message Assinar &Mensagem + Reset all sign message fields Repor todos os campos de assinatura da mensagem + + Clear &All Limpar &Tudo + + &Verify Message &Verificar Mensagem + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Introduza o endereço de assinatura, mensagem (assegura que copia exatamente quebras de linha, espaços, tabuladores, etc.) e a assinatura abaixo para verificar a mensagem. Tenha atenção para não ler mais na assinatura do que o que estiver na mensagem assinada, para evitar ser enganado por um atacante que se encontre entre si e quem assinou a mensagem. + The address the message was signed with (e.g. Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) O endereço da mensagem foi assinado com (ex: Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) + Verify the message to ensure it was signed with the specified Gridcoin address Verificar a mensagem para assegurar que foi assinada com o endereço Gridcoin especificado + Reset all verify message fields Repor todos os campos de verificação de mensagem + + Enter a Gridcoin address (e.g. S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) Insira um endereço Gridcoin (ex: S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) - Click "Sign Message" to generate signature - Clique "Assinar Mensagem" para gerar a assinatura + + Click "Sign Message" to generate signature + Clique "Assinar Mensagem" para gerar a assinatura + Enter Gridcoin signature Insira assinatura do Gridcoin + + The entered address is invalid. O endereço introduzido é inválido. + + + + Please check the address and try again. Por favor verifique o endereço e tente de novo. + + The entered address does not refer to a key. O endereço introduzido não se refere a uma chave. + Wallet unlock was cancelled. O desbloqueio da carteira foi cancelado. + Private key for the entered address is not available. A chave privada para o endereço introduzido não está disponível. + Message signing failed. Assinatura de mensagem falhou. + Message signed. Mensagem assinada. + The signature could not be decoded. A assinatura não pode ser descodificada. + + Please check the signature and try again. Por favor, verifique a assinatura e tente novamente. + The signature did not match the message digest. A assinatura não condiz com o conteúdo da mensagem. + Message verification failed. Verificação da mensagem falhou. + Message verified. Mensagem verificada. @@ -3471,183 +4907,246 @@ Isto significa que uma taxa de pelo menos %2 é necessária. TransactionDesc + Open for %n more block(s) - - Aberto para mais %n bloco(s) - Aberto para mais %n bloco(s) - + Aberto para mais %n bloco(s)Aberto para mais %n bloco(s)Aberto por mais %n bloco(s) + Open until %1 Aberto até %1 + conflicted conflito + + %1/offline + %1/offline + + + %1/unconfirmed %1/não confirmada + %1 confirmations %1 confirmações + Status Estado + , has not been successfully broadcast yet , ainda não foi anunciada com sucesso + , broadcast through %n node(s) - - - - + , transmitida através de %n nó, transmitida através de %n nós, transmitida através de %n nó + Date Data + + Source Origem + Generated in CoinBase Gerada na CoinBase + Mined - PoS Minada - PoS + Mined - PoS+RR Minada - PoS+RR + Mined - Orphaned Minada - Orfã + PoS Side Stake Received PoS Side Stake Recebido + PoS+RR Side Stake Received PoS+RR Side Stake Recebido + PoS Side Stake Sent PoS Side Stake Enviado + PoS+RR Side Stake Sent PoS+RR Side Stake Enviado + + MRC Payment Received + Pagamento MRC Recebido + + + + MRC Payment Sent + Pagamento MRC Enviado + + + Mined - Superblock Minada - Super Bloco + Mined - Unknown Minada - Desconhecido + + From De + unknown desconhecido + + + To Para + + own address endereço próprio + label etiqueta + + + + + Credit Crédito + matures in %n more block(s) - - matura em %n bloco(s) - matura em %n bloco(s) - + matura em %n bloco(s)matura em %n bloco(s)matura em %n bloco(s) + not accepted não aceite + + + + Debit Débito + Transaction fee Taxa de transação + Net amount Valor líquido + + Message Mensagem + Comment Comentário + TX ID ID da TX + + Block Hash Hash do Bloco + Transaction Stake Data Dados de Stake da Transação - Gridcoin generated coins must mature 110 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. - As moedas gerados pelo Gridcoin devem maturar durante 110 blocos antes de poderem ser gastas. Quando gerou este bloco, ele foi transmitido à rede para ser adicionado à blockchain. Se falhar a entrada na cadeia, o seu estado será alterado para "não aceite" e não será possível gastá-la. Isto pode acontecer ocasionalmente se outro nó gerar um bloco com segundos de diferença do seu. + + Gridcoin generated coins must mature 110 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + As moedas gerados pelo Gridcoin devem maturar durante 110 blocos antes de poderem ser gastas. Quando gerou este bloco, ele foi transmitido à rede para ser adicionado à blockchain. Se falhar a entrada na cadeia, o seu estado será alterado para "não aceite" e não será possível gastá-la. Isto pode acontecer ocasionalmente se outro nó gerar um bloco com segundos de diferença do seu. + Transaction Debits/Credits Débitos/Créditos da Transação + Transaction Data Dados da Transação + Transaction Inputs Entradas de Transação + Amount Valor + true verdadeiro + false falso @@ -3655,14 +5154,17 @@ Isto significa que uma taxa de pelo menos %2 é necessária. TransactionDescDialog + Transaction details Detalhes da transação + This pane shows a detailed description of the transaction Esta janela mostra uma descrição detalhada da transação + C&lose F&echar @@ -3670,149 +5172,202 @@ Isto significa que uma taxa de pelo menos %2 é necessária. TransactionTableModel + Date Data + Type Tipo + Address Endereço + Amount Quantia + Open for %n more block(s) - - Aberto por mais %n bloco(s) - Aberto por mais %n bloco(s) - + Aberto por mais %n bloco(s)Aberto por mais %n bloco(s)Aberto por mais %n bloco(s) + Open until %1 Aberto até %1 + + Offline + Offline + + + Unconfirmed Não confirmado + Confirming (%1 of %2 recommended confirmations)<br> Confirmando (%1 de %2 confirmações recomendadas)<br> + Confirmed (%1 confirmations) Confirmada (%1 confirmações) + Conflicted Em Conflito + Immature (%1 confirmations, will be available after %2)<br> Imatura (%1 confirmações, estará disponível depois de %2)<br> + This block was not received by any other nodes<br> and will probably not be accepted! Este bloco não foi recebido por outros nós<br> e provavelmente não será aceite! + Generated but not accepted Gerado mas não aceite + Received with Recebido com + Received from Recebido de + Sent to Enviado para + Payment to yourself Pagamento ao próprio + Mined - PoS Minada - PoS + Mined - PoS+RR Minada - PoS+RR + Mined - Orphaned Minada - Orfã + PoS Side Stake Received PoS Side Stake Recebido + PoS+RR Side Stake Received PoS+RR Side Stake Recebido + PoS Side Stake Sent PoS Side Stake Enviado + PoS+RR Side Stake Sent PoS+RR Side Stake Enviado + + MRC Payment Received + Pagamento MRC Recebido + + + + MRC Payment Sent + Pagamento MRC Enviado + + + Mined - Superblock Minada - Super Bloco + Mined - Unknown Minada - Desconhecido + Beacon Advertisement Anúncio do Beacon + Poll - Votação + Sondagem + Vote Voto + + Manual Rewards Claim Request + Solicitação Manual de Reivindicação de Recompensas + + + Message Mensagem + (n/a) (n/d) + Transaction status. Hover over this field to show number of confirmations. Estado da transação. Coloque ponteiro por cima deste campo para mostrar o número de confirmações. + Date and time that the transaction was received. Data e hora a que esta transação foi recebida. + Type of transaction. Tipo de transação. + Destination address of transaction. Endereço de destino da transação. + Amount removed from or added to balance. Quantia adicionada ou retirada do saldo. @@ -3820,139 +5375,178 @@ Isto significa que uma taxa de pelo menos %2 é necessária. TransactionView + Transaction History Histórico de Transações + Search by address or label Pesquisar por endereço ou etiqueta + All Time De Sempre + Today Hoje + This week Esta semana + This month Este mês + Last month Mês passado + This year Este ano + Range... Alcance... + All Types Todos os Tipos + Received with Recebida com + Sent to Enviada para + To yourself Para si + Mined Mineradas + Other Outro + Min amount Quantia mínima + Copy address Copiar endereço + Copy label Copiar etiqueta + Copy amount Copiar quantia + Copy transaction ID Copiar ID da transação + Edit label Editar etiqueta + Show transaction details Mostrar detalhes da transação + Export Transaction Data Exportar Dados da Transação + Comma separated file Name of CSV file format Ficheiro separado por vírgulas + Confirmed Confirmado + Date Data + Type Tipo + Label Etiqueta + Address Endereço + Amount Quantia + + ID + ID + + + Error exporting Erro ao exportar + Could not write to file %1. Não foi possível escrever para o ficheiro %1. + Range: Alcance: + to para @@ -3960,14 +5554,17 @@ Isto significa que uma taxa de pelo menos %2 é necessária. UpgradeQt + E&xit S&air + Quit application Sair da aplicação + &File &Ficheiro @@ -3975,6 +5572,7 @@ Isto significa que uma taxa de pelo menos %2 é necessária. VoteWizard + Vote Voto @@ -3982,6 +5580,7 @@ Isto significa que uma taxa de pelo menos %2 é necessária. VoteWizardBallotPage + Submit Vote Submeter Voto @@ -3989,14 +5588,17 @@ Isto significa que uma taxa de pelo menos %2 é necessária. VoteWizardSummaryPage + Vote Submitted Voto Submetido + Your vote will tally with the next block. O seu voto coincidirá com o próximo bloco. + Copy ID Copiar ID @@ -4004,61 +5606,87 @@ Isto significa que uma taxa de pelo menos %2 é necessária. VotingModel + + Please unlock the wallet. Por favor desbloqueie a carteira. + Poll not found. - Votação não encontrada. + Sondagem não encontrada. + Failed to load poll from disk - Falhou o carregamento das votações do disco + Falhou o carregamento das sondagens do disco VotingPage + Voting A Votar + Polls - Votações + Sondagem + Search by title Pesquisar por título + View as list. Ver como lista. + + + Alt+T + Alt+T + + + View as table. Ver como tabela. + Sort by... Ordenar por... + + Alt+S + Alt+S + + + &Refresh &Atualizar + Create &Poll - Criar &Votação + Criar &Sondagem - A new poll is available. Press "Refresh" to load it. - Uma nova votação está disponível. Carregue em "Atualizar" para a mostrar. + + A new poll is available. Press "Refresh" to load it. + Uma nova sondagem está disponível. Carregue em "Atualizar" para a mostrar. + &Active &Ativo + &Completed &Concluído @@ -4066,6 +5694,7 @@ Isto significa que uma taxa de pelo menos %2 é necessária. WalletModel + Sending... Enviando... @@ -4073,546 +5702,1042 @@ Isto significa que uma taxa de pelo menos %2 é necessária. bitcoin-core + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s Ocorreu um erro ao definir a porta %u do serviço RPC ao escutar em IPv6, a reverter para IPv4: %s + An error occurred while setting up the RPC port %u for listening on IPv4: %s Ocorreu um erro ao definir a porta %u do serviço RPC ao escutar em IPv4: %s + Usage: Utilização: + List commands Listar comandos + A poll with a yes/no/abstain response type cannot include any additional custom choices. - Uma votação com uma resposta do tipo sim/não/abster-se, não pode incluir quaisquer escolhas adicionais. + Uma sondagem com uma resposta do tipo sim/não/abster-se, não pode incluir quaisquer escolhas adicionais. + Cannot obtain a lock on data directory %s. %s is probably already running and using that directory. Não foi possível cadear a diretoria de dados %s. %s já está provavelmente a utilizar essa diretoria. + Cannot obtain a lock on data directory %s. %s is probably already running. Não foi possivel cadear a diretoria de dados %s. %s já está provavelmente em execução. + + Check that BOINC is installed and that you have the correct path in the config file if you installed it to a nonstandard location. + Verifique que o BOINC está instalado e que tem o caminho correto no ficheiro de configuração, caso o tenha instalado numa localização não definida por padrão. + + + + Error: Clock skew is 5 minutes or greater. Please check your clock settings. + Erro: O sincronização do relógio é de 5 minutos ou mais. Verifique as definições do seu relógio. + + + Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. Erro: A transação foi rejeitada. Isso pode acontecer se algumas das na sua moedas na carteira já tiverem sido gastas, se tiver utilizado uma cópia da wallet.dat e as moedas não tiverem sido marcadas como gastas aqui. + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds Erro: Esta transação devido à sua quantia, complexidade ou utilização de fundos recebidos recentemente, necessita de uma taxa de transação de pelo menos %s + + For initiatives related to the Gridcoin community not covered by other poll types. + Para iniciativas relacionadas com a Comunidade Gridcoin, não abrangidas por outros tipos de sondagem. + + + + For polls about community representation, public relations, and communications. + Para sondagens sobre representação comunitária, relações públicas e comunicações. + + + + Please check your network and also check the config file and ensure your addnode entries are up-to-date. If you recently started the wallet, you may want to wait another few minutes for connections to build up and test again. Please see https://gridcoin.us/wiki/config-file.html and https://addnodes.cycy.me/. + Por favor, verifique a sua rede e também o ficheiro de configuração e certifique-se de que as suas entradas addnode estão atualizadas. Se iniciou recentemente a carteira, poderá querer aguardar mais alguns minutos para que as ligações sejam estabelecidas e testar novamente. Consulte https://gridcoin.us/wiki/config-file.html e https://addnodes.cycy.me/. + + + + Please ensure that you have followed the process to advertise and verify your beacon. You can use the research wizard (the beacon button on the overview screen). + Certifique-se de que seguiu o processo para publicitar e verificar o seu beacon. Pode utilizar o assistente de pesquisa (o botão beacon no ecrã de resumo). + + + + Poll additional field value "%s" for field name "%s" exceeds %s characters. + A sondagem do valor de campo adicional "%s" para o nome de campo "%s" excede os %s caracteres. + + + + Proposals related to Gridcoin management like poll requirements and funding. + Propostas relacionadas com a gestão do Gridcoin, como requisitos de sondagem e financiamento. + + + + Propose additions or removals of computing projects for research reward eligibility. + Propor adições ou remoções de projetos de computação para a elegibilidade de prémios de investigação. + + + + The IP for the port test site is unable to be resolved. This could mean your DNS is not working correctly. The wallet may operate without DNS, but it could be severely degraded, especially if the wallet is new and a database of prior successful connections has not been built up. Please check your computer and ensure name resolution is operating correctly. + Não é possível resolver o IP do site de teste de portas. Isto pode significar que o seu DNS não está a funcionar corretamente. A carteira pode funcionar sem DNS, mas pode ser gravemente degradada, especialmente se a carteira for nova e não tiver sido criada uma base de dados de ligações anteriores bem sucedidas. Verifique o seu computador e certifique-se de que a resolução de nomes está a funcionar corretamente. + + + + The connection to the port test site was refused. This could be a transient problem with the port test site, but could also be an issue with your firewall. If you are also failing the connection test, your firewall is most likely blocking network communications from the Gridcoin client. + A ligação ao site de teste de portas foi recusada. Isto pode ser um problema transitório com o site de teste de portas, mas também pode ser um problema com a sua firewall. Se também estiver a falhar o teste de ligação, a sua firewall está provavelmente a bloquear as comunicações de rede do cliente Gridcoin. + + + + The network has experienced a low-level error and this probably means your IP address or other network connection parameters are not configured correctly. Please check your network configuration on your computer. + A rede sofreu um erro de baixo nível, o que provavelmente significa que o seu endereço IP ou outros parâmetros de ligação à rede não estão corretamente configurados. Verifique a configuração da rede no seu computador. + + + + The network is reporting an unspecified socket error. If you also are failing the connection test, then please check your computer's network configuration. + A rede está a reportar um erro de socket não especificado. Se também falhar o teste de ligação, verifique a configuração de rede do seu computador. + + + + The port test site is closed on port. This could be a transient problem with the port test site, but could also be an issue with your firewall. If you are also failing the connection test, your firewall is most likely blocking network communications from the Gridcoin client. + O sítio de teste de portas está fechado na porta. Isto pode ser um problema transitório com o site de teste de portas, mas também pode ser um problema com a sua firewall. Se também estiver a falhar o teste de ligação, a sua firewall está muito provavelmente a bloquear as comunicações de rede do cliente Gridcoin. + + + + The wallet has less than five connections to the network and is unable to connect to an NTP server to check your computer clock. This is not necessarily a problem. You can wait a few minutes and try the test again. + A carteira tem menos de cinco ligações à rede e não consegue ligar-se a um servidor NTP para verificar o relógio do seu computador. Isto não é necessariamente um problema. Pode esperar alguns minutos e repetir o teste novamente. + + + The wallet will now shutdown. Please start your wallet to begin sync from zero A carteira irá encerrar. Por favor, inicie a sua carteira para começar a sincronização do zero + + There is a new leisure version available and you should upgrade as soon as practical. + Existe uma nova versão de lazer disponível e deve ser atualizada assim que possível. + + + + There is a new mandatory version available and you should upgrade as soon as possible to ensure your wallet remains in consensus with the network. + Existe uma nova versão obrigatória disponível e deve atualizá-la o mais rapidamente possível para garantir que a sua carteira se mantém em consenso com a rede. + + + + Verify (1) that you have BOINC installed correctly, (2) that you have attached at least one whitelisted project, (3) that you advertised your beacon with the same email as you use for your BOINC project(s), and (4) that the CPID on the overview screen matches the CPID when you login to your BOINC project(s) online. + Verifique (1) se o BOINC está instalado corretamente, (2) se adicionou pelo menos um projeto da whitelist, (3) se anunciou seu beacon com o mesmo e-mail que usa para o(s) seu(s) projeto(s) BOINC e (4) se o CPID no ecrã de visão geral corresponde ao CPID quando inicia sessão no(s) seu(s) projeto(s) BOINC on-line. + + + + Verify that you have actually completed workunits for the projects you have attached and that you have authorized the export of statistics. Please see https://gridcoin.us/guides/whitelist.htm. + Verifique se as unidades de trabalho dos projetos que adicionou foram efetivamente concluídas e se autorizou a exportação de estatísticas. Consultar https://gridcoin.us/guides/whitelist.htm. + + + WARNING: A mandatory release is available. Please upgrade as soon as possible. AVISO: Uma versão obrigatória do cliente Gridcoin está disponível. Por favor atualize o mais rapidamente possível. + + Warning: Clock skew is between 3 and 5 minutes. Please check your clock settings. + Aviso: O desvio do relógio situa-se entre 3 e 5 minutos. Verifique as definições do seu relógio. + + + + Warning: ETTS is > 90 days. It will take a very long time to receive your research rewards by staking - increase balance or use MRC + Aviso: O ETTS é > 90 dias. Vai demorar muito tempo a receber as suas recompensas de investigação por staking - aumente o saldo ou utilize o MRC + + + + Warning: ETTS is infinite. No coins to stake - increase balance or use MRC + Aviso: O ETTS é infinito. Não há moedas para realizar stake - aumente o saldo ou use o MRC + + + Warning: Ending this process after Stage 2 will result in syncing from 0 or an incomplete/corrupted blockchain. - Aviso: Acabar este processo antes da Fase 2 irão resultar numa sincronização do "0", ou num blockchain incompleto/corrupto. + Aviso: Acabar este processo antes da Fase 2 irá resultar numa sincronização do "0", ou numa cadeia de blocos incompleta/corrupta. + + + + You have no balance and will be unable to retrieve your research rewards when solo crunching by staking. You can use MRC to retrieve your rewards, or you should acquire GRC to stake so you can retrieve your research rewards. Please see https://gridcoin.us/guides/boinc-install.htm. + Não tens saldo e não será possível recuperar as tuas recompensas de investigação quando estiveres a fazer crunch a solo por staking. Podes usar MRC para recuperar as tuas recompensas, ou deverás adquirir GRC para fazer stake e poderes recuperar as tuas recompensas de investigação. Consulte https://gridcoin.us/guides/boinc-install.htm. + + + + You will not be able to stake because you have less than %1 connection(s). Please check your network and also check the config file and ensure your addnode entries are up-to-date. If you recently started the wallet, you may want to wait another few minutes for connections to build up and then test again. Please see https://gridcoin.us/wiki/config-file.html and https://addnodes.cycy.me/. + Não será possível realizar stake porque tem menos de %1 ligação(ões). Por favor, verifique a sua rede e verifique também o ficheiro de configuração e certifique-se de que as suas entradas addnode estão atualizadas. Se iniciou recentemente a carteira, pode querer esperar mais alguns minutos para que as ligações se estabeleçam e depois testar novamente. Consulte https://gridcoin.us/wiki/config-file.html e https://addnodes.cycy.me/. + + + + Your balance is low given the current network difficulty to stake in a reasonable period of time to retrieve your research rewards when solo crunching. You should consider acquiring more GRC to stake more often, or else use MRC to retrieve your rewards. + O seu saldo é baixo dada a dificuldade atual da rede em realizar stake num período de tempo razoável para recuperar as suas recompensas de investigação quando faz crunch a solo. Deve considerar a aquisição de mais GRC para realizar stake mais vezes, ou então usar MRC para recuperar as suas recompensas. + + + + Your balance is too low given the current network difficulty to stake in a reasonable period of time to retrieve your research rewards when solo crunching. You can use MRC to retrieve your rewards, or you should acquire more GRC to stake more often. + O teu saldo é demasiado baixo tendo em conta a dificuldade atual da rede, para poderes realizar stake num período de tempo razoável para recuperares as tuas recompensas de investigação quando fazes crunch a solo. Podes usar MRC para recuperar as tuas recompensas, ou deverás adquirir mais GRC para realizar stake mais vezes. + + + + Your clock in your computer is significantly off from UTC or network time and this may seriously degrade the operation of the wallet, including maintaining connection to the network. You should check your time and time zone settings for your computer. A very common problem is the off by one hour caused by a time zone issue or problems with daylight savings time. + O relógio do seu computador está significativamente desfasado da hora UTC ou da hora da rede, o que pode degradar seriamente o funcionamento da carteira, incluindo a manutenção da ligação à rede. Deve verificar as definições da hora e do fuso horário do seu computador. Um problema muito comum é o desfasamento de uma hora causado por um problema de fuso horário ou por problemas com a hora de Verão. + + + + Your difficulty is extremely low and your wallet is almost certainly forked. Please ensure you are running the latest version and try removing the blockchain database and resyncing from genesis using the menu option. (Note this will take 2-4 hours.) + A sua dificuldade é extremamente baixa e a sua carteira está quase de certeza bifurcada. Por favor, certifique-se de que está a correr a versão mais recente e tente remover a base de dados da cadeia de blocos e voltar a sincronizar a partir do génese usando a opção de menu. (Note que isso levará de 2-4 horas). + + + + Your difficulty is low but your wallet is still in initial sync. Please recheck it later to see if this passes. + A sua dificuldade é baixa, mas a sua carteira ainda está na sincronização inicial. Volte a verificar mais tarde para ver se isto ficou resolvido. + + + + Your difficulty is very low and your wallet is probably forked. Please ensure you are running the latest version and try removing the blockchain database and resyncing from genesis using the menu option. (Note this will take 2-4 hours.) + A sua dificuldade é muito baixa e a sua carteira está provavelmente bifurcada. Por favor, certifique-se de que está a correr a versão mais recente e tente remover a base de dados da cadeia de blocos e volte a sincronizar a partir da génese usando a opção de menu. (Observe que isso levará de 2-4 horas). + + + + Your outbound connection count is critically low. Please check your the config file and ensure your addnode entries are up-to-date. If you recently started the wallet, you may want to wait another few minutes for connections to build up and then test again. Please see https://gridcoin.us/wiki/config-file.html and https://addnodes.cycy.me/. + A sua contagem de ligações de saída é criticamente baixa. Por favor, verifique o seu ficheiro de configuração e certifique-se de que as suas entradas addnode estão atualizadas. Se iniciou recentemente a carteira, pode ter de esperar mais alguns minutos para que as ligações se estabeleçam e depois testar novamente. Consulte https://gridcoin.us/wiki/config-file.html e https://addnodes.cycy.me/. + + + + Your outbound connection count is low. Please check your the config file and ensure your addnode entries are up-to-date. If you recently started the wallet, you may want to wait another few minutes for connections to build up and then test again. Please see https://gridcoin.us/wiki/config-file.html and https://addnodes.cycy.me/. + A sua contagem de ligações de saída é baixa. Por favor, verifique o seu ficheiro de configuração e certifique-se de que as suas entradas addnode estão atualizadas. Se iniciou recentemente a carteira, pode ter de esperar mais alguns minutos para que as ligações se estabeleçam e depois testar novamente. Consulte https://gridcoin.us/wiki/config-file.html e https://addnodes.cycy.me/. + + + + Your wallet is not in sync and has not previously been in sync during this run, please wait for the wallet to sync and retest. If there are other failures preventing the wallet from syncing, please correct those items and retest to see if this test passes. + A sua carteira não está sincronizada e não esteve anteriormente sincronizada durante esta execução, aguarde que a carteira sincronize e volte a testar. Se existirem outras falhas que impeçam a sincronização da carteira, corrija esses itens e volte a testar para ver se este teste é concluído com sucesso. + + + + Your wallet is out of sync with the network but was in sync before. If this fails there is likely a severe problem that is preventing the wallet from syncing. If the lack of sync is due to network connection issues, you will see failures on the network connection test(s). If the network connections pass, but your wallet fails this test, and continues to fail this test on repeated attempts with a few minutes in between, this could indicate a more serious issue. In that case you should check the debug log to see if it sheds light on the cause for no sync. + A sua carteira está fora de sincronia com a rede, mas estava sincronizada anteriormente. Se isto falhar, é provável que exista um problema grave que esteja a impedir a sincronização da carteira. Se a falta de sincronização se dever a problemas de ligação à rede, verá falhas no(s) teste(s) de ligação à rede. Se as ligações de rede passarem, mas a sua carteira falhar este teste, e continuar a falhar este teste em tentativas repetidas com alguns minutos de intervalo, isto pode indicar um problema mais sério. Nesse caso, deve verificar o registo de depuração para ver se este esclarece a causa da falha na sincronização. + + + + Your wallet is still in initial sync. If this is a sync from the beginning (genesis), the sync process can take from 2 to 4 hours, or longer on a slow computer. If you have synced your wallet before but you just started the wallet up, then wait a few more minutes and retry the diagnostics again. + A sua carteira ainda está na sincronização inicial. Se se tratar de uma sincronização desde o início (génese), o processo de sincronização pode demorar de 2 a 4 horas, ou mais num computador lento. Se já sincronizou a sua carteira antes, mas acabou de a iniciar, aguarde mais alguns minutos e tente executar novamente o diagnóstico. + A poll choice cannot be empty. - A escolha duma votação não pode estar vazia. + A escolha duma sondagem não pode estar vazia. + Are you sure you want to cancel the snapshot operation? Tem a certeza que quer cancelar a operação de snapshot? + Balance too low to create a contract. Balanço demasiado baixo para criar um contrato. + CPID Count Contagem CPID + CPID count polls are not supported. - Contagem de votações CPID não são suportadas. + Contagem de sondagens CPID não são suportadas. + Cancel snapshot operation? Cancelar operação de snapshot? + Cancel Cancelar - Cannot write to data directory '%s'; check permissions. - Não foi possível escrever na diretoria de dados '%s', verifique permissões. + + Cannot write to data directory '%s'; check permissions. + Não foi possível escrever na diretoria de dados '%s', verifique permissões. - Click "Show Details" to view changes in latest update. - Clique em "Mostrar Detalhes" para ver as alterações da ultima atualização. + + Click "Show Details" to view changes in latest update. + Clique em "Mostrar Detalhes" para ver as alterações da ultima atualização. + Community Comunidade + Could not create transaction. See debug.log. Não foi possível criar transação. Ver debug.log + Duplicate poll additional field: %s - Duplicar campo adicional na votação: %s + Duplicar campo adicional na sondagem: %s + Duplicate poll choice: %s - Duplicar escolhas da votação: %s + Duplicar escolhas da sondagem: %s + Duplicate response for poll choice: %s - Duplicar respostas para escolha da votação %s + Duplicar respostas para escolha da sondagem %s + Entire balance reserved Saldo inteiro reservado + Error loading %s: Wallet corrupted Erro a carregar %s: Carteira corrompida + Error: Transaction creation failed. Erro: Criação de transação falhou. + Exceeded the number of choices in the poll: %s - Excedidos número de escolhas na votação: %s + Excedidos número de escolhas na sondagem: %s + Failed to download snapshot.zip; See debug.log Falhou a transferência do snapshot.zip; Ver debug.log + Failed to rename bootstrap file to .old for backup purposes. Falhou a alteração de nome por motivos de backups no ficheiro bootstrap para .old. + + Failed: 80 block difficulty is less than + Falhou: a dificuldade de 80 blocos é menor que + + + Failed: Count = Falhou: Contagem = + Fees Collected Taxas coletadas + Files: Ficheiros: + For opinion or casual polls without any particular requirements. - Para opiniões ou votações casuais sem requisitos especiais. + Para opiniões ou sondagens casuais sem requisitos especiais. + + + + GB) + GB) + + GB/ + GB/ + + + Get help for a command Obter ajuda para um comando + Governance Governança + Gridcoin Update Available Atualização do Gridcoin Disponível + + Gridcoin + Gridcoin + + + Initializing beacon registry from stored history... Inicializando registo de beacons do histórico armazenado... + Initializing local researcher context... Inicializando contexto de investigador local... + Initializing research reward accounting... Inicializando contagem de recompensas de investigação... + Insufficient funds. Fundos insuficientes. + + KB/s + KB/s + + + Loading beacon history... Carregando histórico de beacons... + Loading superblock cache... Carregando cache do super bloco... + Local version: Versão local: + + MB/s + MB/s + + + Magnitude+Balance Magnitude+Balanço + Magnitude-only polls are not supported. - Magnitude-pools apenas não são suportadas. + Sondagens de Magnitude apenas não são suportadas. + + + + Marketing + Marketing + Multiple Choice Escolha Múltipla + N/A N/D + No UTXOs available due to reserve balance Sem UTXOs disponíveis devido ao balanço de reserva + No address contains %s GRC in %s UTXOs or fewer. Sem endereços contendo %s GRC em %s UTXOs ou menos. + No coins Sem moedas + No eligible outputs greater than 1 GRC. Sem saídas elegíveis maiores que 1 GRC. + No mature coins Sem moedas maduras + No wallet available. Carteira não disponível. + Outbound communication to TCP port %1 appears to be blocked. Comunicação de saída na porta TCP %1 parece estar bloqueada. + Outbound communication to TCP port Comunicação de saída na porta TCP + Outreach Divulgação + Participant Count Contagem de Participantes + Participant count polls are not supported. - Contagens de participantes das votações não são suportadas. + Contagens de participantes das sondagens não são suportadas. + + Passed: 80 block difficulty is + Sucesso: A dificuldade de 80 blocos é + + + + Passed: Count = + Sucesso: Contagem = + + + + Passed: ETTS = + Sucesso: ETTS = + + + Please enter a poll discussion website URL. - Por favor insira o URL do website para a discussão da votação. + Por favor insira o URL do sítio web para a discussão da sondagem. + Please enter a poll title. - Por favor insira o titulo da votação. + Por favor insira o titulo da sondagem. + Please enter at least one response. Por favor insira pelo menos uma resposta. + Please enter at least two poll choices. - Por favor insira pelo menos duas escolhas na votação. + Por favor insira pelo menos duas escolhas na sondagem. + + Poll additional field name "%s" exceeds %s characters. + O nome do campo adicional da sondagem "%s" excede os %s caracteres. + + + + Poll cannot contain more than %s additional fields + A sondagem não pode conter mais de %s campos adicionais + + + Poll cannot contain more than %s choices. - Votação não pode conter mais do que %s escolhas. + A sondagem não pode conter mais do que %s escolhas. - Poll choice "%s" exceeds %s characters. - Escolha %s da votação excede os %s carateres. + + Poll choice "%s" exceeds %s characters. + Escolha %s da sondagem excede os %s carateres. + Poll discussion URL cannot exceed %s characters. - URL de discussão da votação não pode exceder os %s carateres. + URL de discussão da sondagem não pode exceder os %s carateres. + Poll duration cannot exceed %s days. - Duração da votação não pode exceder os %s dias. + Duração da sondagem não pode exceder os %s dias. + Poll duration must be at least %s days. - Duração da votação tem de durar pelo menos %s dias. + Duração da sondagem tem de durar pelo menos %s dias. + Poll has already finished. - Votação já terminou. + A sondagem já terminou. + Poll only allows a single choice. - Votação permite apenas uma escolha única. + A sondagem permite apenas uma escolha única. + Poll question cannot exceed %s characters. - Questão da votação não pode exceder %s carateres. + Questão da sondagem não pode exceder %s carateres. + Poll signature failed. See debug.log. - Assinatura da votação falhou. Veja debug.log + Assinatura da sondagem falhou. Ver debug.log + Poll title cannot exceed %s characters. - Título da votação não pode exceder %s carateres. + Título da sondagem não pode exceder %s carateres. + + Poll with that title already exists. Please choose another title. + Já existe uma sondagem com esse título. Por favor, escolha outro título. + + + + Pool + Pool + + + + Project Listing + Listagem de Projetos + + + + Propose a change to Gridcoin at the protocol level. + Propor uma alteração ao Gridcon ao nível do protocolo. + + + + Propose marketing initiatives like ad campaigns. + Propor iniciativas de marketing como campanhas publicitárias. + + + + Protocol Development + Protocolo de Desenvolvimento + + + Quorum Hash Quórum de Hashes + Reindexing blockchain from on disk block data files... - Reindexando blockchain dos ficheiros de dados no disco... + Reindexando cadeia de blocos dos ficheiros de dados de blocos no disco... + Replaying contracts... Recarregando contratos.. + Reset Blockchain Data: Blockchain data removal failed. - Repor Dados da Blockchain: Remoção de dados da Blockchain falhou. + Repor os Dados da Cadeia de Blocos: Remoção de dados da cadeia de blocos falhou. + Reset Blockchain Data: Blockchain data removal was a success - Repor Dados da Blockchain: Remoção de dados da Blockchain realizada com sucesso + Repor os Dados da Cadeia de Blocos: Remoção de dados da cadeia de blocos realizada com sucesso + Send command to -server or gridcoinresearchd Enviar comando para -server ou gridcoinresearchd + Snapshot extraction failed! Cleaning up any extracted data Extração do Snapshot falhou! Limpando dados já extraídos + Snapshot operation canceled due to an invalid snapshot zip. Operação de snapshot cancelada devido a um snapshot.zip inválido. + Snapshot operation canceled. Operação de snapshot cancelada. + Snapshot operation successful! Operação de snapshot concluída com sucesso! + Stage (1/4): Downloading snapshot.zip: Speed Etapta (1/4): Transferindo o snapshot.zip: Velocidade + Stage (2/4): Verify SHA256SUM of snapshot.zip Etapa (2/4): Verificando SHA256SUM do snapshot.zip + Stage (3/4): Cleanup blockchain data - Etapa (3/4): Limpando dados do blockchain + Etapa (3/4): Limpando dados da cadeia de blocos + Stage (4/4): Extracting snapshot.zip Etapa (4/4): Extraindo o snapshot.zip + + Survey + Questionário + + + + The field is not well-formed. + O campo não está bem formado. + + + + The field list is not well-formed. + A lista do campo não está bem formada. + + + The wallet is now shutting down. Please restart your wallet. A carteira está a encerrar. Por favor reinicie a sua carteira. + The wallet will now shutdown. A carteira irá agora encerrar. + + This wallet is almost certainly forked. + A carteira está quase de certeza bifurcada. + + + + This wallet is probably forked. + A carteira está provavelmente bifurcada. + + + + Unable to create the PID file '%s': %s + Não foi possível criar o ficheiro PID "%s': %s + + + + Unknown poll type. This should never happen. + Tipo de sondagem desconhecida. Isto nunca deverá acontecer. + + + + Warning: 45 days < ETTS = + Aviso: 45 dias < ETTS = + + + + Warning: 80 block difficulty is less than + Aviso: A dificuldade de 80 blocos é menor que + + + + Warning: Cannot connect to NTP server + Aviso: Não foi possível ligar ao servidor NTP + + + + Warning: Count = + Aviso: Contagem = + + + + Wrong Payload version specified for current block height. + Versão de carga útil incorreta especificada para a altura do bloco atual. + + + Yes/No/Abstain Sim/Não/Abster-se + + You should check your time and time zone settings for your computer. + Deve verificar as definições de hora e fuso horário do seu computador. + + + You will need to delete the following. Irá necessitar de eliminar o seguinte. - "%s" is not a valid poll choice. - %s não é uma escolha válida da votação. + + "%s" is not a valid poll choice. + "%s" não é uma escolha válida da sondagem. + + + + appears to be blocked. + parece estar bloqueado. + leisure opcional + mandatory obrigatória + unknown desconhecido + Balance Balanço + The %s developers Os %s desenvolvedores + + Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. + Erro: Argumento não suportado -socks encontrado. Definir a versão SOCKS não é mais possível, são apenas suportadas proxies SOCKS5. + + + Block Version Versão do Bloco + + Block file load progress + Progresso do carregamento do ficheiro de blocos + + + Block not in index Bloco em falha no index + Block read failed Bloco lido falhou + Blocks Loaded Blocos Carregados + Blocks Verified Blocos Verificados + Boinc Reward Recompensa do BOINC + + CPID + CPID + + + Client Version Versão do Cliente + Datadir: Diretório de dados: + Difficulty Dificuldade + Directories: Diretorias: + Disabled by configuration Desabilitado por configuração + ERROR ERRO + Eligible for Research Rewards Elegível para Pesquisar Recompensas + Error: Wallet locked, unable to create transaction. Erro: Carteira bloqueada, não foi possível criar transação + GitHub version: Versão GitHub: + Height Tamanho + Importing blockchain data file(s). - Importando ficheiro(s) de dados da blockchain. + Importando ficheiro(s) de dados da cadeia de blocos. + Interest Interesse - Invalid amount for -peertimeout=<amount>: '%s' - Quantia inválida para -peertimeout=<amount>: '%s' + + Invalid amount for -peertimeout=<amount>: '%s' + Quantia inválida para -peertimeout=<amount>: '%s' + Invalid team Equipa inválida + Is Superblock É um Super Bloco + + Latest Version GitHub data response: + Versão mais recente da resposta de dados do GitHub: + + + Loading Network Averages... Carregando Médias de Rede... + Loading banlist... A carregar lista de proibidos... + + Magnitude + Magnitude + + + Malformed CPID CPID Mal Formado + Organization Empresa + Project email mismatch Email de projeto incompatível + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. Atenção: -paytxfee está definida com um valor muito elevado! Esta é a taxa que irá pagar se enviar uma transação. + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. Atenção: wallet.dat corrupto, dados recuperados! Wallet.dat original guardada como wallet.{timestamp}.bak em %s; se o seu saldo ou transações estiverem incorretos, deverá restaurar duma cópia de segurança. + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. Atenção: erro ao ler wallet.dat! Todas as chaves foram lidas correctamente, mas os dados de transação ou entradas do livro de endereços podem estar em falta ou incorretos. + Error: Transaction creation failed Erro: Criação de transação falhou + Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. Erro: A transação foi rejeitada. Isto pode acontecer se algumas das moedas na sua carteira já tiverem sido gastas, por exemplo se as usou na cópia da sua wallet.dat, mas não foram marcadas como gastas aqui. + Failed to listen on any port. Use -listen=0 if you want this. Falhou a escutar em qualquer porta. Use -listen=0 se quiser isto. + Single Choice Escolha Única + Snapshot Process Complete! Processo de Snapshot Completo! + Snapshot Process Has Begun. Processo de Snapshot Iniciou. + To use the %s option Para utilizar as opções %s + %s, you must set a rpcpassword in the configuration file: %s It is recommended you use the following random password: @@ -4622,7 +6747,7 @@ rpcpassword=%s The username and password MUST NOT be the same. If the file does not exist, create it with owner-readable-only file permissions. It is also recommended to set alertnotify so you are notified of problems; -for example: alertnotify=echo %%s | mail -s "Gridcoin Alert" admin@foo.com +for example: alertnotify=echo %%s | mail -s "Gridcoin Alert" admin@foo.com %s, tem de difinir uma palavra-passe rcp no ficheiro de configuração: %s @@ -4633,22 +6758,31 @@ rpcpassword=%s O nome de utilizador e palavra-passa NÃO devem ser a mesma. Se o ficheiro não existir, crie-o com permissões de escrita. Também é recomendado que defina um alarme de notificação para que seja notificado de problemas; -por exemplo: alertnotify=echo %%s | mail -s "Gridcoin Alert" admin@foo.com +por exemplo: alertnotify=echo %%s | mail -s "Gridcoin Alert" admin@foo.com + Due to the failure to delete the blockchain data you will be required to manually delete the data before starting your wallet. - Devido à falha em eliminar os dados da blockchain, irá necessitar de eliminar manualmente os dados antes de começar de iniciar a sua carteira. + Devido à falha na eliminação dos dados da cadeia de blocos, ser-lhe-á solicitado que elimine manualmente os dados antes de iniciar a sua carteira. + Failed to download snapshot as mandatory client is available for download. Falhou a transferência do snapshot porque existe uma atualização obrigatória da aplicação. + + Failure to do so will result in undefined behaviour or failure to start wallet. + Se não o fizer, o resultado será um comportamento indefinido ou uma falha no arranque da carteira. + + + Unable to download a snapshot, as the wallet has detected that a new mandatory version is available for install. The mandatory upgrade must be installed before the snapshot can be downloaded and applied. Não foi possível transferir o snapshot, porque a carteira detetou que uma versão obrigatória mais recente, está disponível para instalar. A atualização obrigatória deve ser instalada antes que o snapshot possa ser transferido e aplicado. + WARNING: Blockchain data may be corrupted. Gridcoin detected bad index entries. This may occur because of an unexpected exit, a power failure, or a late software upgrade. @@ -4659,7 +6793,7 @@ Please exit Gridcoin, open the data directory, and delete: Your wallet will re-download the blockchain. Your balance may appear incorrect until the synchronization finishes. - AVISO: A Blockchain pode estar corrompida. + AVISO: A Cadeia de Blocos pode estar corrompida. O Gridcoin detetou entradas incorretas do índice. Isto pode ocorrer devido uma fecho inesperado, falha de energia ou uma atualização da aplicação. @@ -4667,10 +6801,11 @@ Por favor saia do Gridcoin, abra a diretoria de dados e, elimine: - os ficheiros blk****.dat - a diretoria txleveldb -A sua carteira irá transferir novamente a blockchain. O seu balanço poder aparecer incorreto até que a sincronização termine. +A sua carteira irá transferir novamente a cadeia de blocos. O seu balanço poder aparecer incorreto até que a sincronização termine. + You must set rpcpassword=<password> in the configuration file: %s If the file does not exist, create it with owner-readable-only file permissions. @@ -4679,238 +6814,307 @@ If the file does not exist, create it with owner-readable-only file permissions. Se o ficheiro não existir, crie-o com permissões de leitura. + Gridcoin version Versão do Gridcoin + + Resetting block chain index to prepare for reindexing... + Repondo o índice da block chain para preparar a reindexação... + + + Stage (1/4): Downloading snapshot.zip: Etapa (1/4): Transferindo o snapshot.zip: + Stage (2/4): Verify SHA256SUM of snapshot.zip: Etapa (2/4): Verificando SHA256SUM do snapshot.zip: + Stage (3/4): Cleanup blockchain data: - Etapa (3/4): Limpar dados da blockchain: + Etapa (3/4): Limpar dados da cadeia de blocos: + Stage (4/4): Extracting snapshot.zip: Etapa (4/4): Extraindo o snapshot.zip: + Staking Only - Investor Mode Para Realizar Stake Apenas - Modo de Investidor + Staking Only - No Eligible Research Projects Para Realizar Stake Apenas - Sem Projetos de Pesquisa Elegíveis + Testnet-only version Versão de rede de testes apenas + Unknown error Erro desconhecido + Unknown Desconhecido + Staking Only - No active beacon A Realizar Stake Apenas - Beacon Inativo + Staking Only - Pool Detected A Realizar Stake Apenas - Pool detetada + Superblock Binary Size Super Bloco de Tamanho Binário + This update is A atualização está + Unknown poll response type. - Tipo de resposta da votação desconhecido. + Tipo de resposta da sondagem desconhecida. + Unknown poll type. - Tipo de votação desconhecido. + Tipo de sondagem desconhecida. + Unknown poll weight type. - Tipo de peso da votação desconhecido. + Tipo de peso da sondagem desconhecido. + None Nenhum + No current polls - Sem votações + Sem sondagens - Invalid amount for -paytxfee=<amount>: '%s' - Quantia inválida para -paytxfee=<amount>: '%s' + + Invalid amount for -paytxfee=<amount>: '%s' + Quantia inválida para -paytxfee=<amount>: '%s' - Invalid amount for -mininput=<amount>: '%s' - Quantia inválida para -mininput=<amount>: '%s' + + Invalid amount for -mininput=<amount>: '%s' + Quantia inválida para -mininput=<amount>: '%s' + Initialization sanity check failed. Gridcoin is shutting down. Inicialização de verificação de sanidade falhou. O Gridcoin está a encerrar. + Wallet %s resides outside data directory %s. A carteira %s reside fora da diretoria de dados %s. + Verifying database integrity... Verificando integridade da base de dados... + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. Erro ao iniciar o ambiente da base de dados %s! Para recuperar, FAÇA UMA CÓPIA DE SEGURANÇA DESSA DIRETORIA, depois remova tudo, exceto o wallet.dat. + wallet.dat corrupt, salvage failed wallet.dat corrupto, recuperação falhou - Invalid -proxy address: '%s' - Endereço -proxy inválido: '%s' + + Invalid -proxy address: '%s' + Endereço -proxy inválido: '%s' - Invalid -tor address: '%s' - Endereço -tor inválido: '%s' + + Invalid -tor address: '%s' + Endereço -tor inválido: '%s' - Cannot resolve -bind address: '%s' - Não foi possível resolver o endereço -bind: '%s' + + Cannot resolve -bind address: '%s' + Não foi possível resolver o endereço -bind: '%s' - Cannot resolve -externalip address: '%s' - Não foi possível resolver o endereço -externalip: '%s' + + Cannot resolve -externalip address: '%s' + Não foi possível resolver o endereço -externalip: '%s' + Invalid amount for -reservebalance=<amount> Quantia inválida para - reservebalance=<amount> + Error loading blkindex.dat Erro ao carregar blkindex.dat + Error loading wallet.dat: Wallet corrupted Erro ao carregar wallet.dat: Carteira corrompida + Error loading wallet.dat: Wallet requires newer version of Gridcoin Erro ao carregar wallet.dat: A carteira necessita de uma versão mais recente do Gridcoin + + Offline + Offline + + + Verifying checkpoints... Verificando checkpoints... + Wallet locked Carteira trancada + Wallet needed to be rewritten: restart Gridcoin to complete A carteira precisa de ser reescrita: reinicie o Gridcoin para concluir + Error loading wallet.dat Erro ao carregar wallet.dat + Importing bootstrap blockchain data file. - Importando ficheiro de dados do bootstrap da blockchain. + Importação do ficheiro de dados da cadeia de blocos bootstrap. + Loading addresses... A carregar os endereços... + Error: could not start node Erro: Não foi possível iniciar o nó + Unable to bind to %s on this computer. Gridcoin is probably already running. Não foi possível ligar ao %s neste computador. O Gridcoin já está possivelmente a ser executado. + Unable to bind to %s on this computer (bind returned error %d, %s) Não foi possível vincular a %s neste computador (ligação retornou erro %d, %s) + Error: Wallet locked, unable to create transaction Erro: Carteira bloqueada, não foi possível criar transação + Error: Wallet unlocked for staking only, unable to create transaction. Erro: Carteira desbloqueada para realizar stake apenas, não foi possível criar transação. + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds Erro: Esta transação devido à sua quantia, complexidade ou utilização de fundos recebidos recentemente, necessita de uma taxa de transação de pelo menos %s + Sending... Enviando... + Invalid amount Quantia inválida - Warning: Please check that your computer's date and time are correct! If your clock is wrong Gridcoin will not work properly. + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Gridcoin will not work properly. Aviso: Por favor verifique que a data e hora do seu computador estão corretos! Se o seu relógio estiver incorreto, o Gridcoin não funcionará bem. + Vote signature failed. See debug.log. - Assinatura da votação falhou. Veja debug.log. + Assinatura da votação falhou. Ver debug.log. + Warning: Disk space is low! Aviso: Pouco disco em espaço! - Unknown network specified in -onlynet: '%s' - Rede desconhecida especificada em -onlynet: '%s' + + Unknown network specified in -onlynet: '%s' + Rede desconhecida especificada em -onlynet: '%s' + Insufficient funds Fundos insuficientes + Loading block index... A carregar o índice de blocos... + Loading wallet... A carregar a carteira... + Cannot write default address Impossível escrever endereço por defeito + Rescanning... Reexaminando... + Done loading Carregamento concluído + Error Erro From 2ead2b2fb3b92cc286d9b93ccd9c5617e41da971 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Fri, 22 Dec 2023 12:00:25 +0000 Subject: [PATCH 02/44] Translate src/qt/locale/bitcoin_en.ts in pt_PT 100% reviewed source file: 'src/qt/locale/bitcoin_en.ts' on 'pt_PT'. --- src/qt/locale/bitcoin_pt_PT.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts index 8439e176bd..5388d090ed 100644 --- a/src/qt/locale/bitcoin_pt_PT.ts +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -2171,7 +2171,7 @@ Isto significa que uma taxa de pelo menos %2 é necessária. Enable Staking - Habilitar Realização de Stake + Ativar Staking From 79af8fc1d543ca2b551d3a769c5a8afa8b38f3cc Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Mon, 29 Jan 2024 18:25:57 -0500 Subject: [PATCH 03/44] Increment version to 5.4.5.6 for development. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b9f1baed24..d1e2fcf553 100755 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 5) define(_CLIENT_VERSION_MINOR, 4) define(_CLIENT_VERSION_REVISION, 5) -define(_CLIENT_VERSION_BUILD, 5) +define(_CLIENT_VERSION_BUILD, 6) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2024) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 861eaf392448e6a911bcf2e2e55744cf8565a5b0 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 4 Feb 2024 10:30:31 -0500 Subject: [PATCH 04/44] Correct small bug in sidestaketablemodel for new sidestake entry Creating a new sidestake entry would result in a percentage of zero, which would have to be edited to the correct value. The entered value is properly handled with this commit. --- src/qt/sidestaketablemodel.cpp | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/qt/sidestaketablemodel.cpp b/src/qt/sidestaketablemodel.cpp index 140307591a..018cb0977e 100644 --- a/src/qt/sidestaketablemodel.cpp +++ b/src/qt/sidestaketablemodel.cpp @@ -238,9 +238,12 @@ bool SideStakeTableModel::setData(const QModelIndex &index, const QVariant &valu prior_total_allocation += allocation; } - GRC::Allocation modified_allocation(value.toDouble() / 100.0); + bool parse_ok = false; + double read_allocation = value.toDouble(&parse_ok) / 100.0; - if (modified_allocation < 0 || prior_total_allocation + modified_allocation > 1) { + GRC::Allocation modified_allocation(read_allocation); + + if (!parse_ok || modified_allocation < 0 || prior_total_allocation + modified_allocation > 1) { m_edit_status = INVALID_ALLOCATION; LogPrint(BCLog::LogFlags::VERBOSE, "INFO: %s: m_edit_status = %i", @@ -359,7 +362,6 @@ QString SideStakeTableModel::addRow(const QString &address, const QString &alloc } GRC::Allocation prior_total_allocation; - GRC::Allocation sidestake_allocation; // Get total allocation of all active/mandatory sidestake entries for (const auto& entry : registry.ActiveSideStakeEntries(GRC::SideStake::FilterFlag::ALL, true)) { @@ -367,21 +369,20 @@ QString SideStakeTableModel::addRow(const QString &address, const QString &alloc } // The new allocation must be parseable as a double, must be greater than or equal to 0, and - // must result in a total allocation of less than 100%. - double read_allocation = 0.0; + // must result in a total allocation of less than or equal to 100%. + bool parse_ok = false; + double read_allocation = allocation.toDouble(&parse_ok) / 100.0; - if (!ParseDouble(allocation.toStdString(), &read_allocation)) { - if (read_allocation < 0.0) { - m_edit_status = INVALID_ALLOCATION; - return QString(); - } + GRC::Allocation sidestake_allocation(read_allocation); - sidestake_allocation += GRC::Allocation(read_allocation / 100.0); + if (!parse_ok || sidestake_allocation < 0 || prior_total_allocation + sidestake_allocation > 1) { + m_edit_status = INVALID_ALLOCATION; - if (prior_total_allocation + sidestake_allocation > 1) { - m_edit_status = INVALID_ALLOCATION; - return QString(); - } + LogPrint(BCLog::LogFlags::VERBOSE, "INFO: %s: m_edit_status = %i", + __func__, + (int) m_edit_status); + + return QString(); } std::string sidestake_description = description.toStdString(); From 1123023c6484be61ce6833936aa50719aa3b56a4 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Mon, 5 Feb 2024 16:58:00 -0500 Subject: [PATCH 05/44] Enhance fraction addition by using gcd of denominators This makes fraction addition more resistant to overflows. --- src/test/util_tests.cpp | 18 +++++++++++++ src/util.h | 58 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 7c29dcf892..fe5410094e 100755 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1385,6 +1385,24 @@ BOOST_AUTO_TEST_CASE(util_Fraction_addition_with_internal_simplification) BOOST_CHECK_EQUAL(sum.IsSimplified(), true); } +BOOST_AUTO_TEST_CASE(util_Fraction_addition_with_internal_gcd_simplification) +{ + Fraction lhs(1, 6); + Fraction rhs(2, 15); + + // gcd(6, 15) = 3, so this really is + // + // 1 * (15/3) + 2 * (6/3) 1 * 5 + 2 * 2 3 + // ---------------------- = ------------- = -- + // 3 * (6/3) * (15/3) 3 * 2 * 5 10 + + Fraction sum = lhs + rhs; + + BOOST_CHECK_EQUAL(sum.GetNumerator(), 3); + BOOST_CHECK_EQUAL(sum.GetDenominator(), 10); + BOOST_CHECK_EQUAL(sum.IsSimplified(), true); +} + BOOST_AUTO_TEST_CASE(util_Fraction_subtraction) { Fraction lhs(2, 3); diff --git a/src/util.h b/src/util.h index 8a300122f0..c591792c18 100644 --- a/src/util.h +++ b/src/util.h @@ -356,10 +356,60 @@ class Fraction { return Fraction(overflow_add(slhs.GetNumerator(), srhs.GetNumerator()), slhs.GetDenominator(), true); } - // Otherwise do the full pattern of getting a common denominator and adding, then simplify... - return Fraction(overflow_add(overflow_mult(slhs.GetNumerator(), srhs.GetDenominator()), - overflow_mult(slhs.GetDenominator(), srhs.GetNumerator())), - overflow_mult(slhs.GetDenominator(), srhs.GetDenominator()), + // Now the more complex case. In general, fraction addition follows this pattern: + // + // a c a * (d/g) + c * (b/g) + // - + - , g = gcd(b, d) => --------------------- where {(b/g), (d/g)} will be elements of the counting numbers. + // b d g * (b/g) * (d/g) + // + // (b/g) and (d/g) are divisible with no remainders precisely because of the definition of gcd. + // + // We have already covered the trivial common denominator case above before bothering to compute the gcd of the + // denominator. + int64_t denom_gcd = std::gcd(slhs.GetDenominator(), srhs.GetDenominator()); + + // We have two special cases. One is where g = b (i.e. d is actually a multiple of b). In this case, + // the expression simplifies to + // + // a * (d/b) + c + // ------------- + // d + if (denom_gcd == slhs.GetDenominator()) { + return Fraction(overflow_add(overflow_mult(slhs.GetNumerator(), srhs.GetDenominator() / slhs.GetDenominator()), + srhs.GetNumerator()), + srhs.GetDenominator(), + true); + } + + // The other is where g = d (i.e. b is actually a multiple of d). In this case, + // the expression simplifies to + // + // a + c * (b/d) + // ------------- + // b + if (denom_gcd == srhs.GetDenominator()) { + return Fraction(overflow_add(overflow_mult(srhs.GetNumerator(), slhs.GetDenominator() / srhs.GetDenominator()), + slhs.GetNumerator()), + slhs.GetDenominator(), + true); + } + + // Otherwise do the full pattern of getting a common denominator (pulling out the gcd of the denominators), + // and adding, then simplify... + // + // This approach is more complex than + // + // a * d + c * b + // ------------- + // b * d + // + // but has the advantage of being more resistant to overflows, especially when the two denominators are related by a large + // gcd. In particular in Gridcoin's application with Allocations, the largest denominator of the allocations is 10000, so + // every allocation denominator in reduced form must be divisible evenly into 10000. This means the majority of fraction + // additions will be the two simpler cases above. + return Fraction(overflow_add(overflow_mult(slhs.GetNumerator(), srhs.GetDenominator() / denom_gcd), + overflow_mult(srhs.GetNumerator(), slhs.GetDenominator() / denom_gcd)), + overflow_mult(denom_gcd, overflow_mult(slhs.GetDenominator() / denom_gcd, srhs.GetDenominator() / denom_gcd)), true); } From 4deec19f02b123afc907ccb866ff4a6e14b5627f Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Tue, 6 Feb 2024 22:27:43 -0500 Subject: [PATCH 06/44] Enhance fraction multiplication overflow resistance This uses the "cross" gcds to do cancellation and increase resistance of overflows for things like (1000 / 999) * (999 / 1000). --- src/test/util_tests.cpp | 23 +++++++++++++++++++++++ src/util.h | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index fe5410094e..8f8bd204f2 100755 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1439,6 +1439,29 @@ BOOST_AUTO_TEST_CASE(util_Fraction_multiplication_with_internal_simplification) BOOST_CHECK_EQUAL(product.IsSimplified(), true); } +BOOST_AUTO_TEST_CASE(util_Fraction_multiplication_with_cross_simplification_overflow_resistance) +{ + + Fraction lhs(std::numeric_limits::max() - 3, std::numeric_limits::max() - 1, false); + Fraction rhs((std::numeric_limits::max() - 1) / (int64_t) 2, (std::numeric_limits::max() - 3) / (int64_t) 2); + + Fraction product; + + // This should NOT overflow + bool overflow = false; + try { + product = lhs * rhs; + } catch (std::overflow_error& e) { + overflow = true; + } + + BOOST_CHECK_EQUAL(overflow, false); + + if (!overflow) { + BOOST_CHECK(product == Fraction(1)); + } +} + BOOST_AUTO_TEST_CASE(util_Fraction_division_with_internal_simplification) { Fraction lhs(-2, 3); diff --git a/src/util.h b/src/util.h index c591792c18..66288783ad 100644 --- a/src/util.h +++ b/src/util.h @@ -435,8 +435,36 @@ class Fraction { Fraction slhs(*this, true); Fraction srhs(rhs, true); - return Fraction(overflow_mult(slhs.GetNumerator(), srhs.GetNumerator()), - overflow_mult(slhs.GetDenominator(), srhs.GetDenominator()), + // Gcd's can be used in multiplication for better overflow resistance as well. + // + // Consider + // a c + // - * -, where a/b and c/d are already simplified (i.e. gcd(a, b) = gcd(c, d) = 1. + // b d + // + // We can have g = gcd(a, d) and h = gcd(c, b), which is with the numerators reversed, since multiplication is + // commutative. This means we have + // + // (c / h) (a / g) + // ------- * ------- . + // (b / h) (d / g) + // + // If we form Fraction(c, b, true) and Fraction(a, d, true), the simplification will determine and divide the numerator and + // denominator by h and g respectively. + // + // A specific example is instructive. + // + // 1998 1000 999 1000 1000 999 1 1 + // ---- * ---- = ---- * ---- = ---- * --- = - * - + // 2000 999 1000 999 1000 999 1 1 + // + // This is a formal form of what grade school teachers called factor cancellation. :). + + Fraction sxlhs(srhs.GetNumerator(), slhs.GetDenominator(), true); + Fraction sxrhs(slhs.GetNumerator(), srhs.GetDenominator(), true); + + return Fraction(overflow_mult(sxlhs.GetNumerator(), sxrhs.GetNumerator()), + overflow_mult(sxlhs.GetDenominator(), sxrhs.GetDenominator()), true); } From 0ccd15354b635e90bb9eb8b0293ca638d55cb54c Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 7 Jan 2024 15:15:22 -0500 Subject: [PATCH 07/44] Make corrections to BeaconRegistry::ActivatePending and Deactivate This commit corrects the algorithms that deal with the expiry of pending beacons during a superblock activation and the inverse, which is the resurrection of pending beacons that were marked expired during the deactivation of a superblock in a chain reorganization scenario. --- src/gridcoin/beacon.cpp | 204 ++++++++++++++++++++++------------------ src/gridcoin/beacon.h | 16 ++++ 2 files changed, 130 insertions(+), 90 deletions(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index d0e70943bb..5a153107ff 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -880,58 +880,74 @@ void BeaconRegistry::ActivatePending( { LogPrint(LogFlags::BEACON, "INFO: %s: Called for superblock at height %i.", __func__, height); - // Activate the pending beacons that are not expired with respect to pending age. + // It is possible that more than one pending beacon with the same CPID can be attempted to be + // activated in the same superblock. The behavior here to agree with the original implementation + // is the last one. Here we are going to use a map keyed by the CPID with the array style insert + // to ensure that the LAST pending beacon verified is the one activated. + BeaconMap verified_beacons; + for (const auto& id : beacon_ids) { auto iter_pair = m_pending.find(id); if (iter_pair != m_pending.end()) { + bool already_found = (verified_beacons.find(iter_pair->second->m_cpid) != verified_beacons.end()); - Beacon_ptr found_pending_beacon = iter_pair->second; + if (already_found) { + LogPrint(LogFlags::BEACON, "INFO: %s: More than one pending beacon verified for the same CPID %s. Overriding previous" + "verified beacon.", + __func__, + iter_pair->second->m_cpid.ToString()); + } - // Create a new beacon to activate from the found pending beacon. - Beacon activated_beacon(*iter_pair->second); + verified_beacons[iter_pair->second->m_cpid] = iter_pair->second; + } + } - // Update the new beacon's prev hash to be the hash of the pending beacon that is being activated. - activated_beacon.m_previous_hash = found_pending_beacon->m_hash; + // Activate the pending beacons that are not expired with respect to pending age. + for (const auto& iter_pair : verified_beacons) { - // We are going to have to use a composite hash for these because activation is not done as - // individual transactions. Rather groups are done in each superblock under one hash. The - // hash of the block hash, and the pending beacon that is being activated's hash is sufficient. - activated_beacon.m_status = BeaconStatusForStorage::ACTIVE; + Beacon_ptr last_pending_beacon = iter_pair.second; - activated_beacon.m_hash = Hash(block_hash, found_pending_beacon->m_hash); + // Create a new beacon to activate from the found pending beacon. + Beacon activated_beacon(*iter_pair.second); - LogPrint(LogFlags::BEACON, "INFO: %s: Activating beacon for cpid %s, address %s, hash %s.", - __func__, - activated_beacon.m_cpid.ToString(), - activated_beacon.GetAddress().ToString(), - activated_beacon.m_hash.GetHex()); - - // It is possible that more than one pending beacon with the same CPID can be attempted to be - // activated in the same superblock. The behavior here to agree with the original implementation - // is the last one. So get rid of any previous one activated/inserted. - auto found_already_activated_beacon = m_beacon_db.find(activated_beacon.m_hash); - if (found_already_activated_beacon != m_beacon_db.end()) - { - m_beacon_db.erase(activated_beacon.m_hash); - } + // Update the new beacon's prev hash to be the hash of the pending beacon that is being activated. + activated_beacon.m_previous_hash = last_pending_beacon->m_hash; - m_beacon_db.insert(activated_beacon.m_hash, height, activated_beacon); + // We are going to have to use a composite hash for these because activation is not done as + // individual transactions. Rather groups are done in each superblock under one hash. The + // hash of the block hash, and the pending beacon that is being activated's hash is sufficient. + activated_beacon.m_status = BeaconStatusForStorage::ACTIVE; - // This is the subscript form of insert. Important here because an activated beacon should - // overwrite any existing entry in the m_beacons map. - m_beacons[activated_beacon.m_cpid] = m_beacon_db.find(activated_beacon.m_hash)->second; + activated_beacon.m_hash = Hash(block_hash, last_pending_beacon->m_hash); - // Remove the pending beacon entry from the pending map. (Note this entry still exists in the historical - // table and the db. - m_pending.erase(iter_pair); - } + LogPrint(LogFlags::BEACON, "INFO: %s: Activating beacon for cpid %s, address %s, hash %s.", + __func__, + activated_beacon.m_cpid.ToString(), + activated_beacon.GetAddress().ToString(), + activated_beacon.m_hash.GetHex()); + + m_beacon_db.insert(activated_beacon.m_hash, height, activated_beacon); + + // This is the subscript form of insert. Important here because an activated beacon should + // overwrite any existing entry in the m_beacons map. + m_beacons[activated_beacon.m_cpid] = m_beacon_db.find(activated_beacon.m_hash)->second; + + // Remove the pending beacon entry from the pending map. (Note this entry still exists in the historical + // table and the db. + m_pending.erase(iter_pair.second->GetId()); } - // Discard pending beacons that are expired with respect to pending age. + // Clear the expired pending beacon set. There is no need to retain expired beacons beyond one SB boundary (which is when + // this method is called) as this gives ~960 blocks of reorganization depth before running into the slight possibility that + // a different SB could verify a different pending beacon that should be resurrected to be verified. + m_expired_pending.clear(); + + // Mark remaining pending beacons that are expired with respect to pending age as expired and move to the expired map. for (auto iter = m_pending.begin(); iter != m_pending.end(); /* no-op */) { PendingBeacon pending_beacon(*iter->second); + // If the pending beacon has expired with no action remove the pending beacon. if (pending_beacon.PendingExpired(superblock_time)) { // Set the expired pending beacon's previous beacon hash to the beacon entry's hash. pending_beacon.m_previous_hash = pending_beacon.m_hash; @@ -948,7 +964,19 @@ void BeaconRegistry::ActivatePending( pending_beacon.m_hash.GetHex()); // Insert the expired pending beacon into the db. - m_beacon_db.insert(pending_beacon.m_hash, height, static_cast(pending_beacon)); + if (!m_beacon_db.insert(pending_beacon.m_hash, height, static_cast(pending_beacon))) { + LogPrintf("WARN: %s: Attempt to insert an expired pending beacon entry for cpid %s in the beacon registry where " + "one with that hash key (%s) already exists.", + __func__, + pending_beacon.m_cpid.ToString(), + pending_beacon.m_hash.GetHex()); + } + + // Insert the expired pending beacon into the m_expired_pending set. We do the find here because the insert above + // created a shared pointer to the beacon object we want to hold a reference to. To save memory we do not want to + // use a copy. + m_expired_pending.insert(m_beacon_db.find(pending_beacon.m_hash)->second); + // Remove the pending beacon entry from the m_pending map. iter = m_pending.erase(iter); } else { @@ -965,12 +993,13 @@ void BeaconRegistry::Deactivate(const uint256 superblock_hash) // Find beacons that were activated by the superblock to be reverted and restore them to pending status. These come // from the beacon db. for (auto iter = m_beacons.begin(); iter != m_beacons.end();) { - Cpid cpid = iter->second->m_cpid; - uint256 activation_hash = Hash(superblock_hash, iter->second->m_previous_hash); // If we have an active beacon whose hash matches the composite hash assigned by ActivatePending... if (iter->second->m_hash == activation_hash) { - // Find the pending beacon entry in the db before the activation. This is the previous state record. + Cpid cpid = iter->second->m_cpid; + + // Find the pending beacon entry in the db before the activation. This is the previous state record. NOTE that this + // find pulls the record from leveldb back into memory if the record had been passivated for memory savings before. auto pending_beacon_entry = m_beacon_db.find(iter->second->m_previous_hash); // If not found for some reason, move on. @@ -1000,64 +1029,59 @@ void BeaconRegistry::Deactivate(const uint256 superblock_hash) } } - // Find pending beacons that were removed from the pending beacon map and marked PENDING_EXPIRED and restore them - // back to pending status. Unfortunately, the beacon_db has to be traversed for this, because it is the only entity - // that has the records at this point. This will only be done very rarely, when a reorganization crosses a - // superblock commit. - auto iter = m_beacon_db.begin(); - - while (iter != m_beacon_db.end()) - { - // The cpid in the historical beacon record to be matched. - Cpid cpid = iter->second->m_cpid; - - uint256 match_hash = Hash(superblock_hash, iter->second->m_previous_hash); - - // If the calculated match_hash matches the key (hash) of the historical beacon record, then - // restore the previous record pointed to by the historical beacon record to the pending map. - if (match_hash == iter->first) - { - uint256 resurrect_pending_hash = iter->second->m_previous_hash; - - if (!resurrect_pending_hash.IsNull()) - { - Beacon_ptr resurrected_pending = m_beacon_db.find(resurrect_pending_hash)->second; - - // Check that the status of the beacon to resurrect is PENDING. If it is not log an error but continue - // anyway. - if (resurrected_pending->m_status != BeaconStatusForStorage::PENDING) - { - error("%s: Superblock hash %s: The beacon for cpid %s pointed to by an EXPIRED_PENDING beacon to be " - "put back in PENDING status does not have the expected status of PENDING. The beacon hash is %s " - "and the status is %i", - __func__, - superblock_hash.GetHex(), - cpid.ToString(), - resurrected_pending->m_hash.GetHex(), - resurrected_pending->m_status.Raw()); - } - - // Put the record in m_pending. - m_pending[resurrected_pending->GetId()] = resurrected_pending; - } - else - { - error("%s: Superblock hash %s: The beacon for cpid %s with an EXPIRED_PENDING status has no valid " - "previous beacon hash with which to restore the PENDING beacon.", + // With the newer m_expired_pending set, the resurrection of expired pending beacons is relatively painless. We traverse + // the m_expired_pending set and simply restore the pending beacon pointed to as the antecedent of each expired beacon in + // the map. This is done by the m_beacon_db.find which will pull the beacon record from leveldb if it does not exist in + // memory, which makes this passivation-proof up to a reorganization depth of the interval between two SB's (approximately + // 960 blocks). + for (const auto& iter : m_expired_pending) { + // Get the pending beacon entry that is the antecedent of the expired entry. + auto pending_beacon_entry = m_beacon_db.find(iter->m_previous_hash); + + // Resurrect pending beacon entry + if (!m_pending.insert(std::make_pair(pending_beacon_entry->second->GetId(), pending_beacon_entry->second)).second) { + LogPrintf("WARN: %s: Resurrected pending beacon entry, hash %s, from expired pending beacon for cpid %s during deactivation " + " of superblock hash %s already exists in the pending beacon map corresponding to beacon address %s.", __func__, + pending_beacon_entry->second->m_hash.GetHex(), + pending_beacon_entry->second->m_cpid.ToString(), superblock_hash.GetHex(), - cpid.ToString()); - } - } //matched EXPIRED_PENDING record + pending_beacon_entry->second->GetAddress().ToString() + ); + } + } - iter = m_beacon_db.advance(iter); - } // m_beacon_db traversal -} + // We clear the expired pending beacon map, as when the chain moves forward (perhaps on a different fork), the SB boundary will + // (during the activation) repopulate the m_expired_pending map with a new set of expired_beacons. (This is very, very likely + // to be the same set, BTW.) + m_expired_pending.clear(); + + // Note that making this foolproof in a reorganization across more than one SB boundary means we would have to repopulate the + // expired pending beacon map from the PREVIOUS set of expired pending beacons. This would require a traversal of the entire + // leveldb beacon structure for beacons, as it is keyed by beacon hash, not CPID or CKeyID. The expense is not worth it. In + // artificial reorgs for testing purposes on testnet, where the chain is reorganized back thousands of blocks and then reorganized + // forward along the same effective branch, the same superblocks will be restored using the same beacon activations as before, + // which means in effect none of the expired beacons are ever used. In a real fork scenario, not repopulating the expired_pending + // map limits the 100% foolproof reorg to the interval between SB's, which is approximately 960 blocks. This depth of reorg + // in an operational network scenario is almost inconceivable, and if it actually happens we have other problems much worse + // than the SLIGHT possibility of a different pending beacon being activated with the committed SB. + + // The original algorithm, which traversed m_beacon_db using an iterator, was actually broken, because passivation removes + // elements from the m_beacon_db in memory map if there is only one remaining reference, which is the m_historical map that holds + // references to all historical (non-current) entries. In the original algorithm, expired_pending entries were created in the + // m_beacon_db, and the pending beacon pointer references were removed from m_pending, but no in memory map other than + // m_historical kept a reference to the expired entry. This qualified the expired entry for passivation, so would + // not necessarily be present to find in an iterator traversal of m_beacon_db. The iterator style traversal of m_beacon_db, unlike + // the find, does NOT have the augmentation to pull passivated items from leveldb not in memory, because this would be + // exceedingly expensive. + } //! //! \brief BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries. This is a specialization of the RegistryDB template -//! HandleCurrentHistoricalEntries specific to Beacons. It handles the pending/active/renawal/expired pending/deleted -//! states and their interaction with the active entries map (m_beacons) and the pending entries map (m_pending). +//! HandleCurrentHistoricalEntries specific to Beacons. It handles the pending/active/renewal/expired pending/deleted +//! states and their interaction with the active entries map (m_beacons) and the pending entries map (m_pending) when loading +//! the beacon history from the beacon leveldb backing store during registry initialization. It is not intended to be used +//! for other specializations/overrides. //! //! \param entries //! \param pending_entries diff --git a/src/gridcoin/beacon.h b/src/gridcoin/beacon.h index df941b8ad4..e11f37dd22 100644 --- a/src/gridcoin/beacon.h +++ b/src/gridcoin/beacon.h @@ -805,6 +805,22 @@ class BeaconRegistry : public IContractHandler BeaconMap m_beacons; //!< Contains the active registered beacons. PendingBeaconMap m_pending; //!< Contains beacons awaiting verification. + //! + //! \brief Contains pending beacons that have expired. + //! + //! Contains pending beacons that have expired but need to be retained until the next SB (activation) to ensure a + //! reorganization will successfully resurrect expired pending beacons back into pending ones up to the depth equal to one SB to + //! the next, which is about 960 blocks. The reason this is necessary is two fold: 1) it makes the lookup for expired + //! pending beacons in the deactivate method much simpler in the case of a reorg across a SB boundary, and 2) it holds + //! a reference to the pending beacon shared pointer object in the history map, which prevents it from being passivated. + //! Otherwise, a passivation event, which would remove the pending deleted beacons, followed by a reorganization across + //! SB boundary could have a small possibility of removing a pending beacon that could be verified in the alternative SB + //! eventually staked. + //! + //! This set is cleared and repopulated at each SB accepted by the node with the current expired pending beacons. + //! + std::set m_expired_pending; + //! //! \brief The member variable that is the instance of the beacon database. This is private to the //! beacon registry and is only accessible by beacon registry functions. From 9904ec247b503ade0ae554bbfff058a66daa2cb8 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Thu, 11 Jan 2024 19:26:23 -0500 Subject: [PATCH 08/44] Add circularity detection and triage in beacon chainlet code --- src/gridcoin/beacon.cpp | 84 ++++++++++++++++++++++++++++++++++++++++- src/gridcoin/beacon.h | 13 ++++++- src/gridcoin/tally.cpp | 7 +--- src/rpc/mining.cpp | 44 ++++++--------------- 4 files changed, 107 insertions(+), 41 deletions(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index 5a153107ff..7f5482eea9 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -375,8 +375,7 @@ bool BeaconRegistry::ContainsActive(const Cpid& cpid) const } //! -//! \brief This resets the in-memory maps of the registry. It does NOT -//! clear the LevelDB storage. +//! \brief This resets the in-memory maps of the registry and the LevelDB backing storage. //! void BeaconRegistry::Reset() { @@ -788,6 +787,87 @@ int BeaconRegistry::GetDBHeight() return height; } +Beacon_ptr BeaconRegistry::GetBeaconChainletRoot(Beacon_ptr beacon, + std::shared_ptr>> beacon_chain_out) +{ + // Given that we have had rare situations where somehow cirularity has occurred in the beacon chainlet, which either + // results in the current hash and previous hash being the same, or even suspected previous hash of another entry pointing + // back to a later beacon this vector is used to detect the circularity. + std::vector encountered_hashes { beacon->m_hash }; + + Cpid cpid = beacon->m_cpid; + + if (beacon_chain_out != nullptr) { + LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: active beacon: timestamp = %" PRId64 ", ctx_hash = %s," + " prev_beacon_ctx_hash = %s", + __func__, + beacon->m_timestamp, + beacon->m_hash.GetHex(), + beacon->m_previous_hash.GetHex()); + + beacon_chain_out->push_back(std::make_pair(beacon->m_hash, beacon->m_timestamp)); + } + + // Walk back the entries in the historical beacon map linked by renewal prev tx hash until the first + // beacon in the renewal chain is found (the original advertisement). The accrual starts no earlier + // than here. + unsigned int i = 0; + + while (beacon->Renewed()) + { + uint256 current_hash = beacon->m_hash; + + beacon = m_beacon_db.find(beacon->m_previous_hash)->second; + + if (beacon_chain_out != nullptr) { + LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: renewal %u beacon: timestamp = %" PRId64 ", ctx_hash = %s," + " prev_beacon_ctx_hash = %s.", + __func__, + i, + beacon->m_timestamp, + beacon->m_hash.GetHex(), + beacon->m_previous_hash.GetHex()); + + beacon_chain_out->push_back(std::make_pair(beacon->m_hash, beacon->m_timestamp)); + } + + if (std::find(encountered_hashes.begin(), encountered_hashes.end(), beacon->m_hash) != encountered_hashes.end()) { + // If circularity is found this is an indication of corruption of beacon state and is fatal. + // Produce an error message, reset the beacon registry, and require a restart of the node. + error("%s: Circularity encountered in beacon ownership chain for beacon with CPID %s, starting at hash %s, " + "at %u linked entries back from the start, with offending hash %s.", + __func__, + cpid.ToString(), + current_hash.GetHex(), + i, + beacon->m_hash.GetHex()); + + std::string str_error = strprintf("ERROR %s: Circularity encountered in beacon ownership chain for beacon with CPID %s, " + "starting at hash %s, at %u linked entries back from the start, with offending hash %s.\n" + "\n" + "The client cannot continue and the beacon history has been reset and will be rebuilt " + "on the next restart. Please restart Gridcoin.", + __func__, + cpid.ToString(), + encountered_hashes[0].GetHex(), + i, + beacon->m_hash.GetHex()); + + Reset(); + + uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR); + + throw std::runtime_error(std::string {"A fatal error has occurred and Gridcoin cannot continue. Please restart."}); + } + + encountered_hashes.push_back(beacon->m_hash); + + ++i; + } + + return beacon; +} + bool BeaconRegistry::NeedsIsContractCorrection() { return m_beacon_db.NeedsIsContractCorrection(); diff --git a/src/gridcoin/beacon.h b/src/gridcoin/beacon.h index e11f37dd22..de57cd0339 100644 --- a/src/gridcoin/beacon.h +++ b/src/gridcoin/beacon.h @@ -13,7 +13,6 @@ #include "gridcoin/contract/registry_db.h" #include "gridcoin/cpid.h" #include "gridcoin/support/enumbytes.h" - #include #include #include @@ -768,6 +767,18 @@ class BeaconRegistry : public IContractHandler //! uint64_t PassivateDB(); + //! + //! \brief This function walks the linked beacon entries back (using the m_previous_hash member) from a provided + //! beacon to find the initial advertisement. Note that this does NOT traverse non-continuous beacon ownership, + //! which occurs when a beacon is allowed to expire and must be reverified under a new key. + //! + //! \param beacon smart shared pointer to beacon entry to begin walking back + //! \param beacon_chain_out shared pointer to UniValue beacon chain out report array + //! \return root (advertisement) beacon entry smart shared pointer + //! + Beacon_ptr GetBeaconChainletRoot(Beacon_ptr beacon, + std::shared_ptr>> beacon_chain_out = nullptr); + //! //! \brief Returns whether IsContract correction is needed in ReplayContracts during initialization //! \return diff --git a/src/gridcoin/tally.cpp b/src/gridcoin/tally.cpp index 2c54e215f4..024745761f 100644 --- a/src/gridcoin/tally.cpp +++ b/src/gridcoin/tally.cpp @@ -1228,15 +1228,12 @@ CAmount Tally::GetNewbieSuperblockAccrualCorrection(const Cpid& cpid, const Supe return accrual; } - Beacon_ptr beacon_ptr = beacon; + Beacon_ptr beacon_ptr; // Walk back the entries in the historical beacon map linked by renewal prev tx hash until the first // beacon in the renewal chain is found (the original advertisement). The accrual starts no earlier // than here. - while (beacon_ptr->Renewed()) - { - beacon_ptr = beacons.GetBeaconDB().find(beacon_ptr->m_previous_hash)->second; - } + beacon_ptr = beacons.GetBeaconChainletRoot(beacon); const CBlockIndex* pindex_baseline = GRC::Tally::GetBaseline(); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 69eb2eaae9..e266f624cf 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -300,47 +300,25 @@ UniValue auditsnapshotaccrual(const UniValue& params, bool fHelp) GRC::Beacon_ptr beacon_ptr = beacon_try; - LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: active beacon: timestamp = %" PRId64 ", ctx_hash = %s," - " prev_beacon_ctx_hash = %s", - __func__, - beacon_ptr->m_timestamp, - beacon_ptr->m_hash.GetHex(), - beacon_ptr->m_previous_hash.GetHex()); + std::vector> beacon_chain_out {}; + + std::shared_ptr>> beacon_chain_out_ptr + = std::make_shared>>(beacon_chain_out); UniValue beacon_chain(UniValue::VARR); - UniValue beacon_chain_entry(UniValue::VOBJ); - - beacon_chain_entry.pushKV("ctx_hash", beacon_ptr->m_hash.GetHex()); - beacon_chain_entry.pushKV("timestamp", beacon_ptr->m_timestamp); - beacon_chain.push_back(beacon_chain_entry); - - // This walks back the entries in the historical beacon map linked by renewal prev tx hash until the first - // beacon in the renewal chain is found (the original advertisement). The accrual starts no earlier than here. - uint64_t renewals = 0; - // The renewals <= 100 is simply to prevent an infinite loop if there is a problem with the beacon chain in the registry. This - // was an issue in post Fern beacon db work, but has been resolved and not encountered since. Still makes sense to leave the - // limit in, which represents 41 years worth of beacon chain at the 150 day standard auto-renewal cycle. - while (beacon_ptr->Renewed() && renewals <= 100) - { - auto iter = beacons.GetBeaconDB().find(beacon_ptr->m_previous_hash); - beacon_ptr = iter->second; + beacon_ptr = beacons.GetBeaconChainletRoot(beacon_ptr, beacon_chain_out_ptr); - LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: renewal %u beacon: timestamp = %" PRId64 ", ctx_hash = %s," - " prev_beacon_ctx_hash = %s.", - __func__, - renewals, - beacon_ptr->m_timestamp, - beacon_ptr->m_hash.GetHex(), - beacon_ptr->m_previous_hash.GetHex()); + for (const auto& iter : *beacon_chain_out_ptr) { + UniValue beacon_chain_entry(UniValue::VOBJ); - beacon_chain_entry.pushKV("ctx_hash", beacon_ptr->m_hash.GetHex()); - beacon_chain_entry.pushKV("timestamp", beacon_ptr->m_timestamp); + beacon_chain_entry.pushKV("ctx_hash", iter.first.GetHex()); + beacon_chain_entry.pushKV("timestamp", iter.second); beacon_chain.push_back(beacon_chain_entry); - - ++renewals; } + int64_t renewals = beacon_chain_out_ptr->size() - 1; + bool retry_from_baseline = false; // Up to two passes. The first is from the start of the current beacon chain for the CPID, the second from the Fern baseline. From 856822012dc3eba31508a88efc42011233c3d212 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sat, 13 Jan 2024 17:45:38 -0500 Subject: [PATCH 09/44] Update beacon status logging in beacon_tests --- src/test/gridcoin/beacon_tests.cpp | 141 +++++++++++++++++++++++++---- 1 file changed, 121 insertions(+), 20 deletions(-) diff --git a/src/test/gridcoin/beacon_tests.cpp b/src/test/gridcoin/beacon_tests.cpp index 39b4feefbc..c1ff4f34f7 100644 --- a/src/test/gridcoin/beacon_tests.cpp +++ b/src/test/gridcoin/beacon_tests.cpp @@ -176,21 +176,100 @@ class BeaconRegistryTest if (ctx->m_action == GRC::ContractAction::ADD) { registry.Add(ctx); + + GRC::Beacon_ptr beacon = registry.FindHistorical(ctx.m_tx.GetHash()); + + if (beacon != nullptr) { + std::cout << "add beacon record: " + << "blockheight = " << ctx.m_pindex->nHeight + << ", hash = " << beacon->m_hash.GetHex() + << ", cpid = " << beacon->m_cpid.ToString() + << ", public key = " << HexStr(beacon->m_public_key) + << ", address = " << beacon->GetAddress().ToString() + << ", timestamp = " << beacon->m_timestamp + << ", hash = " << beacon->m_hash.GetHex() + << ", prev beacon hash = " << beacon->m_previous_hash.GetHex() + << ", status = " << beacon->StatusToString() + << std::endl; + } } if (ctx->m_action == GRC::ContractAction::REMOVE) { registry.Delete(ctx); + + GRC::Beacon_ptr beacon = registry.FindHistorical(ctx.m_tx.GetHash()); + + if (beacon != nullptr) { + std::cout << "delete beacon record: " + << "blockheight = " << ctx.m_pindex->nHeight + << ", hash = " << beacon->m_hash.GetHex() + << ", cpid = " << beacon->m_cpid.ToString() + << ", public key = " << HexStr(beacon->m_public_key) + << ", address = " << beacon->GetAddress().ToString() + << ", timestamp = " << beacon->m_timestamp + << ", hash = " << beacon->m_hash.GetHex() + << ", prev beacon hash = " << beacon->m_previous_hash.GetHex() + << ", status = " << beacon->StatusToString() + << std::endl; + } } } // Activate the pending beacons that are now verified, and also mark expired pending beacons expired. if (pindex->IsSuperblock()) { + std::vector pending_beacon_hashes; + + for (const auto& iter : element.m_verified_beacons) { + auto found_beacon_iter = registry.PendingBeacons().find(iter); + + if (found_beacon_iter != registry.PendingBeacons().end()) { + pending_beacon_hashes.push_back(found_beacon_iter->second->m_hash); + } + } + registry.ActivatePending(element.m_verified_beacons, pindex->nTime, block_hash, pindex->nHeight); + + for (const auto& iter : pending_beacon_hashes) { + uint256 activated_beacon_hash = Hash(pindex->GetBlockHash(), iter); + + GRC::Beacon_ptr activated_beacon = registry.FindHistorical(activated_beacon_hash); + + if (activated_beacon != nullptr) { + std::cout << "activated beacon record: " + << "blockheight = " << pindex->nHeight + << ", hash = " << activated_beacon->m_hash.GetHex() + << ", cpid = " << activated_beacon->m_cpid.ToString() + << ", public key = " << HexStr(activated_beacon->m_public_key) + << ", address = " << activated_beacon->GetAddress().ToString() + << ", timestamp = " << activated_beacon->m_timestamp + << ", hash = " << activated_beacon->m_hash.GetHex() + << ", prev beacon hash = " << activated_beacon->m_previous_hash.GetHex() + << ", status = " << activated_beacon->StatusToString() + << std::endl; + } + } + + for (const auto& iter : registry.ExpiredBeacons()) { + if (iter != nullptr) { + std::cout << "expired beacon record: " + << "blockheight = " << pindex->nHeight + << ", hash = " << iter->m_hash.GetHex() + << ", cpid = " << iter->m_cpid.ToString() + << ", public key = " << HexStr(iter->m_public_key) + << ", address = " << iter->GetAddress().ToString() + << ", timestamp = " << iter->m_timestamp + << ", hash = " << iter->m_hash.GetHex() + << ", prev beacon hash = " << iter->m_previous_hash.GetHex() + << ", status = " << iter->StatusToString() + << std::endl; + } + + } } } @@ -200,6 +279,17 @@ class BeaconRegistryTest for (const auto& iter : registry.Beacons()) { m_beacons_init[iter.first] = *iter.second; + + std::cout << "init beacon record: " + << "hash = " << iter.second->m_hash.GetHex() + << ", cpid = " << iter.second->m_cpid.ToString() + << ", public key = " << HexStr(iter.second->m_public_key) + << ", address = " << iter.second->GetAddress().ToString() + << ", timestamp = " << iter.second->m_timestamp + << ", hash = " << iter.second->m_hash.GetHex() + << ", prev beacon hash = " << iter.second->m_previous_hash.GetHex() + << ", status = " << iter.second->StatusToString() + << std::endl; } m_init_number_beacons = m_beacons_init.size(); @@ -241,6 +331,17 @@ class BeaconRegistryTest for (const auto& iter : registry.Beacons()) { m_beacons_reinit[iter.first] = *iter.second; + + std::cout << "reinit beacon record: " + << "hash = " << iter.second->m_hash.GetHex() + << ", cpid = " << iter.second->m_cpid.ToString() + << ", public key = " << HexStr(iter.second->m_public_key) + << ", address = " << iter.second->GetAddress().ToString() + << ", timestamp = " << iter.second->m_timestamp + << ", hash = " << iter.second->m_hash.GetHex() + << ", prev beacon hash = " << iter.second->m_previous_hash.GetHex() + << ", status = " << iter.second->StatusToString() + << std::endl; } m_reinit_number_beacons = m_beacons_reinit.size(); @@ -314,7 +415,7 @@ class BeaconRegistryTest << ", timestamp = " << left.second->m_timestamp << ", hash = " << left.second->m_hash.GetHex() << ", prev beacon hash = " << left.second->m_previous_hash.GetHex() - << ", status = " << ToString(left.second->m_status.Raw()) + << ", status = " << left.second->StatusToString() << std::endl; } @@ -348,8 +449,8 @@ class BeaconRegistryTest std::cout << "init_beacon prev beacon hash = " << left_beacon_ptr->m_previous_hash.GetHex() << ", reinit_beacon prev beacon hash = " << right_beacon_iter->second->m_previous_hash.GetHex() << std::endl; - std::cout << "init_beacon status = " << ToString(left_beacon_ptr->m_status.Raw()) - << ", reinit_beacon status = " << ToString(right_beacon_iter->second->m_status.Raw()) << std::endl; + std::cout << "init_beacon status = " << left_beacon_ptr->StatusToString() + << ", reinit_beacon status = " << right_beacon_iter->second->StatusToString() << std::endl; } } @@ -376,7 +477,7 @@ class BeaconRegistryTest << ", timestamp = " << left.second->m_timestamp << ", hash = " << left.second->m_hash.GetHex() << ", prev beacon hash = " << left.second->m_previous_hash.GetHex() - << ", status = " << ToString(left.second->m_status.Raw()) + << ", status = " << left.second->StatusToString() << std::endl; } @@ -410,8 +511,8 @@ class BeaconRegistryTest std::cout << "reinit_beacon prev beacon hash = " << left_beacon_ptr->m_previous_hash.GetHex() << ", init_beacon prev beacon hash = " << right_beacon_iter->second->m_previous_hash.GetHex() << std::endl; - std::cout << "reinit_beacon status = " << ToString(left_beacon_ptr->m_status.Raw()) - << ", init_beacon status = " << ToString(right_beacon_iter->second->m_status.Raw()) << std::endl; + std::cout << "reinit_beacon status = " << left_beacon_ptr->StatusToString() + << ", init_beacon status = " << right_beacon_iter->second->StatusToString() << std::endl; } } @@ -440,7 +541,7 @@ class BeaconRegistryTest << ", timestamp = " << beacon.m_timestamp << ", hash = " << beacon.m_hash.GetHex() << ", prev beacon hash = " << beacon.m_previous_hash.GetHex() - << ", status = " << ToString(beacon.m_status.Raw()) + << ", status = " << beacon.StatusToString() << std::endl; } @@ -457,7 +558,7 @@ class BeaconRegistryTest << ", timestamp = " << beacon.m_timestamp << ", hash = " << beacon.m_hash.GetHex() << ", prev beacon hash = " << beacon.m_previous_hash.GetHex() - << ", status = " << ToString(beacon.m_status.Raw()) + << ", status = " << beacon.StatusToString() << std::endl; } } @@ -486,7 +587,7 @@ class BeaconRegistryTest << ", timestamp = " << left.second.m_timestamp << ", hash = " << left.second.m_hash.GetHex() << ", prev beacon hash = " << left.second.m_previous_hash.GetHex() - << ", status = " << ToString(left.second.m_status.Raw()) + << ", status = " << left.second.StatusToString() << std::endl; } else if (left_beacon != right->second) @@ -512,8 +613,8 @@ class BeaconRegistryTest std::cout << "init_beacon prev beacon hash = " << left_beacon.m_previous_hash.GetHex() << ", reinit_beacon prev beacon hash = " << right->second.m_previous_hash.GetHex() << std::endl; - std::cout << "init_beacon status = " << ToString(left_beacon.m_status.Raw()) - << ", reinit_beacon status = " << ToString(right->second.m_status.Raw()) << std::endl; + std::cout << "init_beacon status = " << left_beacon.StatusToString() + << ", reinit_beacon status = " << right->second.StatusToString() << std::endl; } } @@ -539,7 +640,7 @@ class BeaconRegistryTest << ", timestamp = " << left.second.m_timestamp << ", hash = " << left.second.m_hash.GetHex() << ", prev beacon hash = " << left.second.m_previous_hash.GetHex() - << ", status = " << ToString(left.second.m_status.Raw()) + << ", status = " << left.second.StatusToString() << std::endl; } @@ -566,8 +667,8 @@ class BeaconRegistryTest std::cout << "reinit_beacon prev beacon hash = " << left_beacon.m_previous_hash.GetHex() << ", init_beacon prev beacon hash = " << right->second.m_previous_hash.GetHex() << std::endl; - std::cout << "reinit_beacon status = " << ToString(left_beacon.m_status.Raw()) - << ", init_beacon status = " << ToString(right->second.m_status.Raw()) << std::endl; + std::cout << "reinit_beacon status = " << left_beacon.StatusToString() + << ", init_beacon status = " << right->second.StatusToString() << std::endl; } } @@ -603,7 +704,7 @@ class BeaconRegistryTest << ", timestamp = " << left_beacon.m_timestamp << ", hash = " << left_beacon.m_hash.GetHex() << ", prev beacon hash = " << left_beacon.m_previous_hash.GetHex() - << ", status = " << ToString(left_beacon.m_status.Raw()) + << ", status = " << left_beacon.StatusToString() << std::endl; } else if (left_beacon != right->second) @@ -633,8 +734,8 @@ class BeaconRegistryTest << ", reinit_pending_beacon prev beacon hash = " << right->second.m_previous_hash.GetHex() << std::endl; - std::cout << ", init_pending_beacon status = " << ToString(left_beacon.m_status.Raw()) - << ", reinit_pending_beacon status = " << ToString(right->second.m_status.Raw()) << std::endl; + std::cout << ", init_pending_beacon status = " << left_beacon.StatusToString() + << ", reinit_pending_beacon status = " << right->second.StatusToString() << std::endl; } } @@ -658,7 +759,7 @@ class BeaconRegistryTest << ", timestamp = " << left.second.m_timestamp << ", hash = " << left.second.m_hash.GetHex() << ", prev beacon hash = " << left.second.m_previous_hash.GetHex() - << ", status = " << ToString(left.second.m_status.Raw()) + << ", status = " << left.second.StatusToString() << std::endl; } else if (left_beacon != right->second) @@ -688,8 +789,8 @@ class BeaconRegistryTest << ", reinit_pending_beacon prev beacon hash = " << right->second.m_previous_hash.GetHex() << std::endl; - std::cout << ", init_pending_beacon status = " << ToString(left_beacon.m_status.Raw()) - << ", reinit_pending_beacon status = " << ToString(right->second.m_status.Raw()) << std::endl; + std::cout << ", init_pending_beacon status = " << left_beacon.StatusToString() + << ", reinit_pending_beacon status = " << right->second.StatusToString() << std::endl; } } From 3e802329f7456d099e93fde60195da1b764027fa Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sat, 13 Jan 2024 19:15:18 -0500 Subject: [PATCH 10/44] Correct BeaconRegistry::FindHistorical --- src/gridcoin/beacon.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index 7f5482eea9..cbdc426302 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -355,9 +355,13 @@ std::vector BeaconRegistry::FindPending(const Cpid& cpid) const const BeaconOption BeaconRegistry::FindHistorical(const uint256& hash) { - BeaconOption beacon = m_beacon_db.find(hash)->second; + auto beacon_iter = m_beacon_db.find(hash); - return beacon; + if (beacon_iter != m_beacon_db.end()) { + return beacon_iter->second; + } + + return {}; } bool BeaconRegistry::ContainsActive(const Cpid& cpid, const int64_t now) const From 95f8fb47bf96bed60a16880edbaa592433b25430 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 14 Jan 2024 10:47:36 -0500 Subject: [PATCH 11/44] Provide access to historical beacon set from beacon registry --- src/gridcoin/beacon.cpp | 8 +++++++- src/gridcoin/beacon.h | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index cbdc426302..ef29d041bc 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -311,6 +311,11 @@ const BeaconRegistry::PendingBeaconMap& BeaconRegistry::PendingBeacons() const return m_pending; } +const std::set& BeaconRegistry::ExpiredBeacons() const +{ + return m_expired_pending; +} + BeaconOption BeaconRegistry::Try(const Cpid& cpid) const { const auto iter = m_beacons.find(cpid); @@ -987,7 +992,8 @@ void BeaconRegistry::ActivatePending( } } - // Activate the pending beacons that are not expired with respect to pending age. + // Activate the pending beacons that are not expired with respect to pending age as of the time of verification (the + // committing of the superblock). for (const auto& iter_pair : verified_beacons) { Beacon_ptr last_pending_beacon = iter_pair.second; diff --git a/src/gridcoin/beacon.h b/src/gridcoin/beacon.h index de57cd0339..ccc34e4b50 100644 --- a/src/gridcoin/beacon.h +++ b/src/gridcoin/beacon.h @@ -588,6 +588,12 @@ class BeaconRegistry : public IContractHandler //! const PendingBeaconMap& PendingBeacons() const; + //! + //! \brief Get the set of beacons that have expired while pending (awaiting verification) + //! \return A reference to the expired pending beacon set. + //! + const std::set& ExpiredBeacons() const; + //! //! \brief Get the beacon for the specified CPID. //! From ffacaf05a7e7f2bc8ef4838ba95936643ce64b11 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 14 Jan 2024 15:25:30 -0500 Subject: [PATCH 12/44] Extend beacon registry db template to cover expired entries This also fixes the HandleCurrentHistoricalEntries specialization in the beacon registry to properly deal with expired pending beacons. --- src/gridcoin/beacon.cpp | 19 +++++++++- src/gridcoin/beacon.h | 1 + src/gridcoin/contract/registry_db.h | 12 ++++-- src/gridcoin/project.cpp | 2 +- src/gridcoin/project.h | 6 ++- src/gridcoin/protocol.cpp | 2 +- src/gridcoin/protocol.h | 6 ++- src/gridcoin/scraper/scraper_registry.cpp | 2 +- src/gridcoin/scraper/scraper_registry.h | 6 ++- src/gridcoin/sidestake.cpp | 2 +- src/gridcoin/sidestake.h | 6 ++- src/test/gridcoin/beacon_tests.cpp | 46 ++++++++++------------- 12 files changed, 70 insertions(+), 40 deletions(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index ef29d041bc..1290f90d52 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -390,6 +390,7 @@ void BeaconRegistry::Reset() { m_beacons.clear(); m_pending.clear(); + m_expired_pending.clear(); m_beacon_db.clear(); } @@ -1182,6 +1183,7 @@ void BeaconRegistry::Deactivate(const uint256 superblock_hash) //! template<> void BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries(GRC::BeaconRegistry::BeaconMap& entries, GRC::BeaconRegistry::PendingBeaconMap& pending_entries, + std::set& expired_entries, const Beacon& entry, entry_ptr& historical_entry_ptr, const uint64_t& recnum, @@ -1216,7 +1218,7 @@ template<> void BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries(GRC::Be if (entry.m_status == BeaconStatusForStorage::ACTIVE || entry.m_status == BeaconStatusForStorage::RENEWAL) { - LogPrint(LogFlags::CONTRACT, "INFO: %s: %ss: entry insert: cpid %s, address %s, timestamp %" PRId64 ", " + LogPrint(LogFlags::CONTRACT, "INFO: %s: %s: entry insert: cpid %s, address %s, timestamp %" PRId64 ", " "hash %s, previous_hash %s, status %s, recnum %" PRId64 ".", __func__, key_type, @@ -1253,6 +1255,15 @@ template<> void BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries(GRC::Be } } + if (entry.m_status == BeaconStatusForStorage::ACTIVE) { + // Note that in the orginal activation, all the activations happen for a superblock, and then the expired_entry set is + // cleared and then new expired entries recorded from the just committed SB. This method operates at the record level, but + // clearing the expired_entries for each ACTIVE record posting will achieve the same effect, because the entries are ordered + // the proper way. It is a little bit of undesired work, but it is not worth the complexity of feeding the boundaries + // of the group of verified beacons to activate. + expired_entries.clear(); + } + if (entry.m_status == BeaconStatusForStorage::EXPIRED_PENDING) { LogPrint(LogFlags::CONTRACT, "INFO: %s: %s: expired pending entry delete: cpid %s, address %s, timestamp %" PRId64 ", " @@ -1268,6 +1279,9 @@ template<> void BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries(GRC::Be recnum ); + // Insert the expired pending entry into the expired entries set. + expired_entries.insert(historical_entry_ptr); + // Delete any entry in the pending map that is marked expired. pending_entries.erase(entry.GetId()); } @@ -1294,7 +1308,7 @@ template<> void BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries(GRC::Be int BeaconRegistry::Initialize() { - int height = m_beacon_db.Initialize(m_beacons, m_pending); + int height = m_beacon_db.Initialize(m_beacons, m_pending, m_expired_pending); LogPrint(LogFlags::BEACON, "INFO: %s: m_beacon_db size after load: %u", __func__, m_beacon_db.size()); LogPrint(LogFlags::BEACON, "INFO: %s: m_beacons size after load: %u", __func__, m_beacons.size()); @@ -1306,6 +1320,7 @@ void BeaconRegistry::ResetInMemoryOnly() { m_beacons.clear(); m_pending.clear(); + m_expired_pending.clear(); m_beacon_db.clear_in_memory_only(); } diff --git a/src/gridcoin/beacon.h b/src/gridcoin/beacon.h index ccc34e4b50..1174db1c1e 100644 --- a/src/gridcoin/beacon.h +++ b/src/gridcoin/beacon.h @@ -811,6 +811,7 @@ class BeaconRegistry : public IContractHandler BeaconStatusForStorage, BeaconMap, PendingBeaconMap, + std::set, HistoricalBeaconMap> BeaconDB; private: diff --git a/src/gridcoin/contract/registry_db.h b/src/gridcoin/contract/registry_db.h index 826aa69bdf..dc51dda00b 100644 --- a/src/gridcoin/contract/registry_db.h +++ b/src/gridcoin/contract/registry_db.h @@ -26,9 +26,11 @@ namespace GRC { //! M: the map type for the entries //! P: the map type for pending entries. This is really only used for beacons. In all other registries it is typedef'd to //! the same as M. +//! X: the map type for expired pending entries. This is really only used for beacons. In all other registries it is typedef'd to +//! the same as M. //! H: the historical map type for historical entries //! -template +template class RegistryDB { public: @@ -62,10 +64,12 @@ class RegistryDB //! \param entries The map of current entries. //! \param pending_entries. The map of pending entries. This is not used in the general template, only in the beacons //! specialization. + //! \param expired_entries. The map of expired pending entries. This is not used in the geenral template, only in the + //! beacons specialization. //! //! \return block height up to and including which the entry records were stored. //! - int Initialize(M& entries, P& pending_entries) + int Initialize(M& entries, P& pending_entries, X& expired_entries) { bool status = true; int height = 0; @@ -169,7 +173,7 @@ class RegistryDB m_historical[iter.second.m_hash] = std::make_shared(entry); entry_ptr& historical_entry_ptr = m_historical[iter.second.m_hash]; - HandleCurrentHistoricalEntries(entries, pending_entries, entry, + HandleCurrentHistoricalEntries(entries, pending_entries, expired_entries, entry, historical_entry_ptr, recnum, key_type); number_passivated += (uint64_t) HandlePreviousHistoricalEntries(historical_entry_ptr); @@ -199,7 +203,7 @@ class RegistryDB //! \param recnum //! \param key_type //! - void HandleCurrentHistoricalEntries(M& entries, P& pending_entries, const E& entry, + void HandleCurrentHistoricalEntries(M& entries, P& pending_entries, X& expired_entries, const E& entry, entry_ptr& historical_entry_ptr, const uint64_t& recnum, const std::string& key_type) { diff --git a/src/gridcoin/project.cpp b/src/gridcoin/project.cpp index 3c92fd8792..6db6511067 100644 --- a/src/gridcoin/project.cpp +++ b/src/gridcoin/project.cpp @@ -495,7 +495,7 @@ int Whitelist::Initialize() { LOCK(cs_lock); - int height = m_project_db.Initialize(m_project_entries, m_pending_project_entries); + int height = m_project_db.Initialize(m_project_entries, m_pending_project_entries, m_expired_project_entries); LogPrint(LogFlags::CONTRACT, "INFO: %s: m_project_db size after load: %u", __func__, m_project_db.size()); LogPrint(LogFlags::CONTRACT, "INFO: %s: m_project_entries size after load: %u", __func__, m_project_entries.size()); diff --git a/src/gridcoin/project.h b/src/gridcoin/project.h index c397e71bb9..5b6ff5fae2 100644 --- a/src/gridcoin/project.h +++ b/src/gridcoin/project.h @@ -618,13 +618,15 @@ class Whitelist : public IContractHandler static void RunDBPassivation(); //! - //! \brief Specializes the template RegistryDB for the ScraperEntry class + //! \brief Specializes the template RegistryDB for the ScraperEntry class. Note that std::set is not + //! actually used. //! typedef RegistryDB, HistoricalProjectEntryMap> ProjectEntryDB; private: @@ -644,6 +646,8 @@ class Whitelist : public IContractHandler ProjectEntryMap m_project_entries; //!< The set of whitelisted projects. PendingProjectEntryMap m_pending_project_entries {}; //!< Not actually used. Only to satisfy the template. + std::set m_expired_project_entries {}; //!< Not actually used. Only to satisfy the template. + ProjectEntryDB m_project_db; //!< The project db member public: diff --git a/src/gridcoin/protocol.cpp b/src/gridcoin/protocol.cpp index 4281f01a15..ec5f0831e9 100644 --- a/src/gridcoin/protocol.cpp +++ b/src/gridcoin/protocol.cpp @@ -482,7 +482,7 @@ int ProtocolRegistry::Initialize() { LOCK(cs_lock); - int height = m_protocol_db.Initialize(m_protocol_entries, m_pending_protocol_entries); + int height = m_protocol_db.Initialize(m_protocol_entries, m_pending_protocol_entries, m_expired_protocol_entries); LogPrint(LogFlags::CONTRACT, "INFO: %s: m_protocol_db size after load: %u", __func__, m_protocol_db.size()); LogPrint(LogFlags::CONTRACT, "INFO: %s: m_protocol_entries size after load: %u", __func__, m_protocol_entries.size()); diff --git a/src/gridcoin/protocol.h b/src/gridcoin/protocol.h index 3e409634e3..37aa39bc53 100644 --- a/src/gridcoin/protocol.h +++ b/src/gridcoin/protocol.h @@ -567,13 +567,15 @@ class ProtocolRegistry : public IContractHandler static void RunDBPassivation(); //! - //! \brief Specializes the template RegistryDB for the ProtocolEntry class + //! \brief Specializes the template RegistryDB for the ProtocolEntry class. Note that std::set + //! is not actually used. //! typedef RegistryDB, HistoricalProtocolEntryMap> ProtocolEntryDB; private: @@ -593,6 +595,8 @@ class ProtocolRegistry : public IContractHandler ProtocolEntryMap m_protocol_entries; //!< Contains the current protocol entries including entries marked DELETED. PendingProtocolEntryMap m_pending_protocol_entries {}; //!< Not used. Only to satisfy the template. + std::set m_expired_protocol_entries {}; //!< Not used. Only to satisfy the template. + ProtocolEntryDB m_protocol_db; public: diff --git a/src/gridcoin/scraper/scraper_registry.cpp b/src/gridcoin/scraper/scraper_registry.cpp index 147253f39a..bf481e0216 100644 --- a/src/gridcoin/scraper/scraper_registry.cpp +++ b/src/gridcoin/scraper/scraper_registry.cpp @@ -527,7 +527,7 @@ int ScraperRegistry::Initialize() { LOCK(cs_lock); - int height = m_scraper_db.Initialize(m_scrapers, m_pending_scrapers); + int height = m_scraper_db.Initialize(m_scrapers, m_pending_scrapers, m_expired_scraper_entries); LogPrint(LogFlags::SCRAPER, "INFO: %s: m_scraper_db size after load: %u", __func__, m_scraper_db.size()); LogPrint(LogFlags::SCRAPER, "INFO: %s: m_scrapers size after load: %u", __func__, m_scrapers.size()); diff --git a/src/gridcoin/scraper/scraper_registry.h b/src/gridcoin/scraper/scraper_registry.h index 5705c15d57..5686c25991 100644 --- a/src/gridcoin/scraper/scraper_registry.h +++ b/src/gridcoin/scraper/scraper_registry.h @@ -606,13 +606,15 @@ class ScraperRegistry : public IContractHandler static void RunDBPassivation(); //! - //! \brief Specializes the template RegistryDB for the ScraperEntry class + //! \brief Specializes the template RegistryDB for the ScraperEntry class. Note that std::set is + //! not actually used. //! typedef RegistryDB, HistoricalScraperMap> ScraperEntryDB; private: @@ -632,6 +634,8 @@ class ScraperRegistry : public IContractHandler ScraperMap m_scrapers; //!< Contains the current scraper entries, including entries marked DELETED. PendingScraperMap m_pending_scrapers {}; //!< Not actually used for scrapers. To satisfy the template only. + std::set m_expired_scraper_entries {}; //!< Not actually used for scrapers. To satisfy the template only. + ScraperEntryDB m_scraper_db; public: diff --git a/src/gridcoin/sidestake.cpp b/src/gridcoin/sidestake.cpp index 938d906c47..adc324b548 100644 --- a/src/gridcoin/sidestake.cpp +++ b/src/gridcoin/sidestake.cpp @@ -712,7 +712,7 @@ int SideStakeRegistry::Initialize() { LOCK(cs_lock); - int height = m_sidestake_db.Initialize(m_mandatory_sidestake_entries, m_pending_sidestake_entries); + int height = m_sidestake_db.Initialize(m_mandatory_sidestake_entries, m_pending_sidestake_entries, m_expired_sidestake_entries); SubscribeToCoreSignals(); diff --git a/src/gridcoin/sidestake.h b/src/gridcoin/sidestake.h index 8702701643..d318fe8043 100644 --- a/src/gridcoin/sidestake.h +++ b/src/gridcoin/sidestake.h @@ -783,13 +783,15 @@ class SideStakeRegistry : public IContractHandler static void RunDBPassivation(); //! - //! \brief Specializes the template RegistryDB for the SideStake class + //! \brief Specializes the template RegistryDB for the SideStake class. Note that std::set + //! is not actually used. //! typedef RegistryDB, HistoricalSideStakeMap> SideStakeDB; private: @@ -827,6 +829,8 @@ class SideStakeRegistry : public IContractHandler MandatorySideStakeMap m_mandatory_sidestake_entries; //!< Contains the mandatory sidestake entries, including DELETED. PendingSideStakeMap m_pending_sidestake_entries {}; //!< Not used. Only to satisfy the template. + std::set m_expired_sidestake_entries {}; //!< Not used. Only to satisfy the template. + SideStakeDB m_sidestake_db; //!< The internal sidestake db object for leveldb persistence. bool m_local_entry_already_saved_to_config = false; //!< Flag to prevent reload on signal if individual entry saved already. diff --git a/src/test/gridcoin/beacon_tests.cpp b/src/test/gridcoin/beacon_tests.cpp index c1ff4f34f7..369eed61c4 100644 --- a/src/test/gridcoin/beacon_tests.cpp +++ b/src/test/gridcoin/beacon_tests.cpp @@ -182,7 +182,6 @@ class BeaconRegistryTest if (beacon != nullptr) { std::cout << "add beacon record: " << "blockheight = " << ctx.m_pindex->nHeight - << ", hash = " << beacon->m_hash.GetHex() << ", cpid = " << beacon->m_cpid.ToString() << ", public key = " << HexStr(beacon->m_public_key) << ", address = " << beacon->GetAddress().ToString() @@ -203,7 +202,6 @@ class BeaconRegistryTest if (beacon != nullptr) { std::cout << "delete beacon record: " << "blockheight = " << ctx.m_pindex->nHeight - << ", hash = " << beacon->m_hash.GetHex() << ", cpid = " << beacon->m_cpid.ToString() << ", public key = " << HexStr(beacon->m_public_key) << ", address = " << beacon->GetAddress().ToString() @@ -242,7 +240,6 @@ class BeaconRegistryTest if (activated_beacon != nullptr) { std::cout << "activated beacon record: " << "blockheight = " << pindex->nHeight - << ", hash = " << activated_beacon->m_hash.GetHex() << ", cpid = " << activated_beacon->m_cpid.ToString() << ", public key = " << HexStr(activated_beacon->m_public_key) << ", address = " << activated_beacon->GetAddress().ToString() @@ -258,7 +255,6 @@ class BeaconRegistryTest if (iter != nullptr) { std::cout << "expired beacon record: " << "blockheight = " << pindex->nHeight - << ", hash = " << iter->m_hash.GetHex() << ", cpid = " << iter->m_cpid.ToString() << ", public key = " << HexStr(iter->m_public_key) << ", address = " << iter->GetAddress().ToString() @@ -279,17 +275,6 @@ class BeaconRegistryTest for (const auto& iter : registry.Beacons()) { m_beacons_init[iter.first] = *iter.second; - - std::cout << "init beacon record: " - << "hash = " << iter.second->m_hash.GetHex() - << ", cpid = " << iter.second->m_cpid.ToString() - << ", public key = " << HexStr(iter.second->m_public_key) - << ", address = " << iter.second->GetAddress().ToString() - << ", timestamp = " << iter.second->m_timestamp - << ", hash = " << iter.second->m_hash.GetHex() - << ", prev beacon hash = " << iter.second->m_previous_hash.GetHex() - << ", status = " << iter.second->StatusToString() - << std::endl; } m_init_number_beacons = m_beacons_init.size(); @@ -314,6 +299,16 @@ class BeaconRegistryTest // Create a copy of the referenced beacon object with a shared pointer to it and store. m_local_historical_beacon_map_init[hash] = std::make_shared(*beacon_ptr); + std::cout << "init beacon db record: " + << ", cpid = " << beacon_ptr->m_cpid.ToString() + << ", public key = " << HexStr(beacon_ptr->m_public_key) + << ", address = " << beacon_ptr->GetAddress().ToString() + << ", timestamp = " << beacon_ptr->m_timestamp + << ", hash = " << beacon_ptr->m_hash.GetHex() + << ", prev beacon hash = " << beacon_ptr->m_previous_hash.GetHex() + << ", status = " << beacon_ptr->StatusToString() + << std::endl; + init_beacon_db_iter = init_beacon_db.advance(init_beacon_db_iter); } @@ -331,17 +326,6 @@ class BeaconRegistryTest for (const auto& iter : registry.Beacons()) { m_beacons_reinit[iter.first] = *iter.second; - - std::cout << "reinit beacon record: " - << "hash = " << iter.second->m_hash.GetHex() - << ", cpid = " << iter.second->m_cpid.ToString() - << ", public key = " << HexStr(iter.second->m_public_key) - << ", address = " << iter.second->GetAddress().ToString() - << ", timestamp = " << iter.second->m_timestamp - << ", hash = " << iter.second->m_hash.GetHex() - << ", prev beacon hash = " << iter.second->m_previous_hash.GetHex() - << ", status = " << iter.second->StatusToString() - << std::endl; } m_reinit_number_beacons = m_beacons_reinit.size(); @@ -366,6 +350,16 @@ class BeaconRegistryTest // Create a copy of the referenced beacon object with a shared pointer to it and store. m_local_historical_beacon_map_reinit[hash] = std::make_shared(*beacon_ptr); + std::cout << "init beacon db record: " + << ", cpid = " << beacon_ptr->m_cpid.ToString() + << ", public key = " << HexStr(beacon_ptr->m_public_key) + << ", address = " << beacon_ptr->GetAddress().ToString() + << ", timestamp = " << beacon_ptr->m_timestamp + << ", hash = " << beacon_ptr->m_hash.GetHex() + << ", prev beacon hash = " << beacon_ptr->m_previous_hash.GetHex() + << ", status = " << beacon_ptr->StatusToString() + << std::endl; + reinit_beacon_db_iter = reinit_beacon_db.advance(reinit_beacon_db_iter); } }; From e014de2c2b50941bbdf61b3713d03b8641e2084a Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 14 Jan 2024 23:42:57 -0500 Subject: [PATCH 13/44] Add expiry check to Beacon::Renewable method The beacon renewable method originally only checked that the minimum amount of time has passed since the advertisement or last renewal. This commit also adds an expiry check, as an expired beacon cannot be successfully renewed. --- src/gridcoin/beacon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index 1290f90d52..e1d8c7b464 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -171,7 +171,7 @@ bool Beacon::Expired(const int64_t now) const bool Beacon::Renewable(const int64_t now) const { - return Age(now) > RENEWAL_AGE; + return (!Expired(now) && Age(now) > RENEWAL_AGE); } bool Beacon::Renewed() const From fd243a1c7ba307146c67105de36b8ce33dbacd3a Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Thu, 25 Jan 2024 12:28:50 -0500 Subject: [PATCH 14/44] Fix reversed arguments on passivation log entry --- src/gridcoin/contract/registry_db.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gridcoin/contract/registry_db.h b/src/gridcoin/contract/registry_db.h index dc51dda00b..804c9a6f8a 100644 --- a/src/gridcoin/contract/registry_db.h +++ b/src/gridcoin/contract/registry_db.h @@ -330,8 +330,8 @@ class RegistryDB LogPrint(BCLog::LogFlags::CONTRACT, "INFO: %s: Passivated %" PRId64 " elements from %s entry db.", __func__, - KeyType(), - number_passivated); + number_passivated, + KeyType()); // Set needs passivation flag to false after passivating the db. m_needs_passivation = false; From 2d0a7b8c6060d5688770e9e58e471250057b8220 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 28 Jan 2024 01:14:30 -0500 Subject: [PATCH 15/44] Increment beacon db version to 3. --- src/gridcoin/beacon.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/gridcoin/beacon.h b/src/gridcoin/beacon.h index 1174db1c1e..64970d7bac 100644 --- a/src/gridcoin/beacon.h +++ b/src/gridcoin/beacon.h @@ -544,13 +544,10 @@ class BeaconRegistry : public IContractHandler //! Version 0: <= 5.2.0.0 //! Version 1: = 5.2.1.0 //! Version 2: 5.2.1.0 with hotfix and > 5.2.1.0 - //! - //! The current version of the beacon db is 2. No changes to the underlying storage have - //! occurred during the refactor to the registry db template, so this version remains unchanged - //! through 5.4.2.0+ + //! Version 3: 5.4.5.5+ //! BeaconRegistry() - : m_beacon_db(2) + : m_beacon_db(3) { }; From 18ed4f8bd3a0db167519e7fbb282afaf6fb79745 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Mon, 29 Jan 2024 12:35:50 -0500 Subject: [PATCH 16/44] Cleanup for thread safety Compiling with Clang 15 caught an extra unneeded lock on cs_main and also an unnecessary exclusive lock required on IsV13Enabled. The gArgs global methods are thread-safe via the internal cs in ArgsManager. --- src/chainparams.h | 2 +- src/qt/mrcmodel.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/chainparams.h b/src/chainparams.h index 16db13777a..908d217824 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -153,7 +153,7 @@ inline bool IsV12Enabled(int nHeight) return nHeight >= Params().GetConsensus().BlockV12Height; } -inline bool IsV13Enabled(int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +inline bool IsV13Enabled(int nHeight) { // The argument driven override temporarily here to facilitate testing. diff --git a/src/qt/mrcmodel.cpp b/src/qt/mrcmodel.cpp index 2ecf594a3b..405ed34b62 100644 --- a/src/qt/mrcmodel.cpp +++ b/src/qt/mrcmodel.cpp @@ -255,8 +255,6 @@ void MRCModel::refresh() EXCLUSIVE_LOCKS_REQUIRED(cs_main) // This is similar to createmrcrequest in many ways, but the state tracking is more complicated. - LOCK(cs_main); - // Record initial block height during init run. if (!m_init_block_height) { m_init_block_height = pindexBest->nHeight; From 95e724e8319dcad46c802661fffbdc751a55818c Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Thu, 1 Feb 2024 19:13:28 -0500 Subject: [PATCH 17/44] Unit tests for BeaconRegistry::GetBeaconChainletRoot --- src/test/gridcoin/beacon_tests.cpp | 439 ++++++++++++++++++++++++++++- 1 file changed, 438 insertions(+), 1 deletion(-) diff --git a/src/test/gridcoin/beacon_tests.cpp b/src/test/gridcoin/beacon_tests.cpp index 369eed61c4..e216919f3a 100644 --- a/src/test/gridcoin/beacon_tests.cpp +++ b/src/test/gridcoin/beacon_tests.cpp @@ -86,6 +86,11 @@ struct TestKey return EncodeBase58(key_id.begin(), key_id.end()); } + static GRC::Cpid Cpid() + { + return GRC::Cpid::Parse("00010203040506070809101112131415"); + } + //! //! \brief Create a beacon payload signature signed by this private key. //! @@ -96,7 +101,27 @@ struct TestKey hasher << GRC::BeaconPayload::CURRENT_VERSION << GRC::Beacon(Public()) - << GRC::Cpid::Parse("00010203040506070809101112131415"); + << Cpid(); + + std::vector signature; + CKey private_key = Private(); + + private_key.Sign(hasher.GetHash(), signature); + + return signature; + } + + //! + //! \brief Create a beacon payload signature signed by this private key. + //! + static std::vector Signature(GRC::BeaconPayload payload) + { + CHashWriter hasher(SER_NETWORK, PROTOCOL_VERSION); + + hasher + << payload.m_version + << payload.m_beacon + << payload.m_cpid; std::vector signature; CKey private_key = Private(); @@ -105,6 +130,7 @@ struct TestKey return signature; } + }; // TestKey @@ -1223,4 +1249,415 @@ BOOST_AUTO_TEST_CASE(beaconstorage_mainnet_test) beacon_registry_test.BeaconDatabaseComparisonChecks_m_pending(); } +BOOST_AUTO_TEST_CASE(beacon_registry_GetBeaconChainletRoot_test) +{ + LogInstance().EnableCategory(BCLog::LogFlags::BEACON); + LogInstance().EnableCategory(BCLog::LogFlags::ACCRUAL); + + FastRandomContext rng(uint256 {0}); + + GRC::BeaconRegistry& registry = GRC::GetBeaconRegistry(); + + // Make sure the registry is reset. + registry.Reset(); + + // This is a trivial initial pending beacon, activation, and two renewals. The typical type of beacon chainlet. + + // Pending beacon + CTransaction tx1 {}; + tx1.nTime = int64_t {1}; + uint256 tx1_hash = tx1.GetHash(); + + CBlockIndex* pindex1 = new CBlockIndex; + pindex1->nVersion = 13; + pindex1->nHeight = 1; + pindex1->nTime = tx1.nTime; + + GRC::Beacon beacon1 {TestKey::Public(), tx1.nTime, tx1_hash}; + beacon1.m_cpid = TestKey::Cpid(); + beacon1.m_status = GRC::Beacon::Status {GRC::BeaconStatusForStorage::PENDING}; + GRC::BeaconPayload beacon_payload1 {2, TestKey::Cpid(), beacon1}; + beacon_payload1.m_signature = TestKey::Signature(beacon_payload1); + + GRC::Contract contract1 = GRC::MakeContract(3, GRC::ContractAction::ADD, beacon_payload1); + GRC::ContractContext ctx1 {contract1, tx1, pindex1}; + + BOOST_CHECK(ctx1.m_contract.CopyPayloadAs().m_cpid == TestKey::Cpid()); + BOOST_CHECK(ctx1.m_contract.CopyPayloadAs().m_beacon.m_status == GRC::BeaconStatusForStorage::PENDING); + BOOST_CHECK(ctx1.m_contract.CopyPayloadAs().m_beacon.m_hash == tx1_hash); + BOOST_CHECK(ctx1.m_tx.GetHash() == tx1_hash); + + registry.Add(ctx1); + + BOOST_CHECK(registry.GetBeaconDB().size() == 1); + + std::vector pending_beacons = registry.FindPending(TestKey::Cpid()); + + BOOST_CHECK(pending_beacons.size() == 1); + + if (pending_beacons.size() == 1) { + BOOST_CHECK(pending_beacons[0]->m_cpid == TestKey::Cpid()); + BOOST_CHECK(pending_beacons[0]->m_hash == tx1_hash); + BOOST_CHECK(pending_beacons[0]->m_previous_hash == uint256 {}); + BOOST_CHECK(pending_beacons[0]->m_public_key == TestKey::Public()); + BOOST_CHECK(pending_beacons[0]->m_status == GRC::BeaconStatusForStorage::PENDING); + BOOST_CHECK(pending_beacons[0]->m_timestamp == tx1.nTime); + } + + // Activation + CBlockIndex* pindex2 = new CBlockIndex; + pindex2->nVersion = 13; + pindex2->nHeight = 2; + pindex2->nTime = int64_t {2}; + uint256* block2_phash = new uint256 {rng.rand256()}; + pindex2->phashBlock = block2_phash; + + std::vector beacon_ids {TestKey::Public().GetID()}; + + registry.ActivatePending(beacon_ids, pindex2->nTime, *pindex2->phashBlock, pindex2->nHeight); + + uint256 activated_beacon_hash = Hash(*block2_phash, pending_beacons[0]->m_hash); + + BOOST_CHECK(registry.GetBeaconDB().size() == 2); + + GRC::Beacon_ptr chainlet_head = registry.Try(TestKey::Cpid()); + + BOOST_CHECK(chainlet_head != nullptr); + + if (chainlet_head != nullptr) { + BOOST_CHECK(chainlet_head->m_hash == activated_beacon_hash); + BOOST_CHECK(chainlet_head->m_status == GRC::BeaconStatusForStorage::ACTIVE); + // Note that the activated beacon's timestamp is actually the same as the timestamp of the PENDING beacon. (Here + // t = 1; + BOOST_CHECK(chainlet_head->m_timestamp == 1); + + std::vector> beacon_chain_out {}; + + std::shared_ptr>> beacon_chain_out_ptr + = std::make_shared>>(beacon_chain_out); + + GRC::Beacon_ptr chainlet_root = registry.GetBeaconChainletRoot(chainlet_head, beacon_chain_out_ptr); + + // There is only one entry in the chainlet.. so the head and root are the same. + BOOST_CHECK(chainlet_root->m_hash == chainlet_head->m_hash); + BOOST_CHECK_EQUAL(beacon_chain_out_ptr->size(), 1); + } + + // Renewal + CTransaction tx3 {}; + tx3.nTime = int64_t {3}; + uint256 tx3_hash = tx3.GetHash(); + CBlockIndex index3 {}; + index3.nVersion = 13; + index3.nHeight = 3; + index3.nTime = tx3.nTime; + + GRC::Beacon beacon3 {TestKey::Public(), tx3.nTime, tx3_hash}; + beacon3.m_cpid = TestKey::Cpid(); + GRC::BeaconPayload beacon_payload3 {2, TestKey::Cpid(), beacon3}; + beacon_payload3.m_signature = TestKey::Signature(beacon_payload3); + + GRC::Contract contract3 = GRC::MakeContract(3, GRC::ContractAction::ADD, beacon_payload3); + GRC::ContractContext ctx3 {contract3, tx3, &index3}; + + registry.Add(ctx3); + + chainlet_head = registry.Try(TestKey::Cpid()); + + BOOST_CHECK(chainlet_head != nullptr); + + if (chainlet_head != nullptr) { + BOOST_CHECK(chainlet_head->m_hash == tx3_hash); + BOOST_CHECK(chainlet_head->m_status == GRC::BeaconStatusForStorage::RENEWAL); + + std::vector> beacon_chain_out {}; + + std::shared_ptr>> beacon_chain_out_ptr + = std::make_shared>>(beacon_chain_out); + + GRC::Beacon_ptr chainlet_root = registry.GetBeaconChainletRoot(chainlet_head, beacon_chain_out_ptr); + + BOOST_CHECK(chainlet_root->m_hash == activated_beacon_hash); + BOOST_CHECK_EQUAL(beacon_chain_out_ptr->size(), 2); + } + + // Second renewal + CTransaction tx4 {}; + tx4.nTime = int64_t {4}; + uint256 tx4_hash = tx4.GetHash(); + CBlockIndex index4 = {}; + index4.nVersion = 13; + index4.nHeight = 2; + index4.nTime = tx4.nTime; + + GRC::Beacon beacon4 {TestKey::Public(), tx4.nTime, tx4_hash}; + beacon4.m_cpid = TestKey::Cpid(); + GRC::BeaconPayload beacon_payload4 {2, TestKey::Cpid(), beacon4}; + beacon_payload4.m_signature = TestKey::Signature(beacon_payload4); + + GRC::Contract contract4 = GRC::MakeContract(3, GRC::ContractAction::ADD, beacon_payload4); + GRC::ContractContext ctx4 {contract4, tx4, &index4}; + registry.Add(ctx4); + + chainlet_head = registry.Try(TestKey::Cpid()); + + BOOST_CHECK(chainlet_head != nullptr); + + if (chainlet_head != nullptr) { + + std::vector> beacon_chain_out {}; + + std::shared_ptr>> beacon_chain_out_ptr + = std::make_shared>>(beacon_chain_out); + BOOST_CHECK(chainlet_head->m_hash == tx4_hash); + BOOST_CHECK(chainlet_head->m_status == GRC::BeaconStatusForStorage::RENEWAL); + + GRC::Beacon_ptr chainlet_root = registry.GetBeaconChainletRoot(chainlet_head, beacon_chain_out_ptr); + + BOOST_CHECK(chainlet_root->m_hash == activated_beacon_hash); + BOOST_CHECK_EQUAL(beacon_chain_out_ptr->size(), 3); + } + + // Let's corrupt the activation beacon to have a previous beacon hash that refers circularly back to the chain head... + bool original_activated_beacon_found = true; + bool circular_corruption_detected = false; + + if (GRC::Beacon_ptr first_active = registry.FindHistorical(activated_beacon_hash)) { + // The original activated beacon m_previous_hash should be the pending beacon hash (beacon1). + BOOST_CHECK(first_active->m_previous_hash == beacon1.m_hash); + BOOST_CHECK(first_active->m_status == GRC::BeaconStatusForStorage::ACTIVE); + + std::vector> beacon_chain_out {}; + + std::shared_ptr>> beacon_chain_out_ptr + = std::make_shared>>(beacon_chain_out); + + // This creates a circular chainlet. + first_active->m_previous_hash = chainlet_head->m_hash; + + beacon_chain_out_ptr->clear(); + + try { + GRC::Beacon_ptr chainlet_root = registry.GetBeaconChainletRoot(chainlet_head, beacon_chain_out_ptr); + } catch (std::runtime_error& e) { + circular_corruption_detected = true; + } + } else { + original_activated_beacon_found = false; + } + + BOOST_CHECK_EQUAL(original_activated_beacon_found, true); + + if (original_activated_beacon_found) { + BOOST_CHECK_EQUAL(circular_corruption_detected, true); + } +} + +BOOST_AUTO_TEST_CASE(beacon_registry_GetBeaconChainletRoot_test_2) +{ + // For right now we will just cut and paste from above, given that the circularity detection causes the registry + // to get reset. + + LogInstance().EnableCategory(BCLog::LogFlags::BEACON); + LogInstance().EnableCategory(BCLog::LogFlags::ACCRUAL); + + FastRandomContext rng(uint256 {0}); + + GRC::BeaconRegistry& registry = GRC::GetBeaconRegistry(); + + // Make sure the registry is reset. + registry.Reset(); + + // This is a trivial initial pending beacon, activation, and two renewals. The typical type of beacon chainlet. + + // Pending beacon + CTransaction tx1 {}; + tx1.nTime = int64_t {1}; + uint256 tx1_hash = tx1.GetHash(); + + CBlockIndex* pindex1 = new CBlockIndex; + pindex1->nVersion = 13; + pindex1->nHeight = 1; + pindex1->nTime = tx1.nTime; + + GRC::Beacon beacon1 {TestKey::Public(), tx1.nTime, tx1_hash}; + beacon1.m_cpid = TestKey::Cpid(); + beacon1.m_status = GRC::Beacon::Status {GRC::BeaconStatusForStorage::PENDING}; + GRC::BeaconPayload beacon_payload1 {2, TestKey::Cpid(), beacon1}; + beacon_payload1.m_signature = TestKey::Signature(beacon_payload1); + + GRC::Contract contract1 = GRC::MakeContract(3, GRC::ContractAction::ADD, beacon_payload1); + GRC::ContractContext ctx1 {contract1, tx1, pindex1}; + + BOOST_CHECK(ctx1.m_contract.CopyPayloadAs().m_cpid == TestKey::Cpid()); + BOOST_CHECK(ctx1.m_contract.CopyPayloadAs().m_beacon.m_status == GRC::BeaconStatusForStorage::PENDING); + BOOST_CHECK(ctx1.m_contract.CopyPayloadAs().m_beacon.m_hash == tx1_hash); + BOOST_CHECK(ctx1.m_tx.GetHash() == tx1_hash); + + registry.Add(ctx1); + + BOOST_CHECK(registry.GetBeaconDB().size() == 1); + + std::vector pending_beacons = registry.FindPending(TestKey::Cpid()); + + BOOST_CHECK(pending_beacons.size() == 1); + + if (pending_beacons.size() == 1) { + BOOST_CHECK(pending_beacons[0]->m_cpid == TestKey::Cpid()); + BOOST_CHECK(pending_beacons[0]->m_hash == tx1_hash); + BOOST_CHECK(pending_beacons[0]->m_previous_hash == uint256 {}); + BOOST_CHECK(pending_beacons[0]->m_public_key == TestKey::Public()); + BOOST_CHECK(pending_beacons[0]->m_status == GRC::BeaconStatusForStorage::PENDING); + BOOST_CHECK(pending_beacons[0]->m_timestamp == tx1.nTime); + } + + // Activation + CBlockIndex* pindex2 = new CBlockIndex; + pindex2->nVersion = 13; + pindex2->nHeight = 2; + pindex2->nTime = int64_t {2}; + uint256* block2_phash = new uint256 {rng.rand256()}; + pindex2->phashBlock = block2_phash; + + std::vector beacon_ids {TestKey::Public().GetID()}; + + registry.ActivatePending(beacon_ids, pindex2->nTime, *pindex2->phashBlock, pindex2->nHeight); + + uint256 activated_beacon_hash = Hash(*block2_phash, pending_beacons[0]->m_hash); + + BOOST_CHECK(registry.GetBeaconDB().size() == 2); + + GRC::Beacon_ptr chainlet_head = registry.Try(TestKey::Cpid()); + + BOOST_CHECK(chainlet_head != nullptr); + + if (chainlet_head != nullptr) { + BOOST_CHECK(chainlet_head->m_hash == activated_beacon_hash); + BOOST_CHECK(chainlet_head->m_status == GRC::BeaconStatusForStorage::ACTIVE); + // Note that the activated beacon's timestamp is actually the same as the timestamp of the PENDING beacon. (Here + // t = 1; + BOOST_CHECK(chainlet_head->m_timestamp == 1); + + std::vector> beacon_chain_out {}; + + std::shared_ptr>> beacon_chain_out_ptr + = std::make_shared>>(beacon_chain_out); + + GRC::Beacon_ptr chainlet_root = registry.GetBeaconChainletRoot(chainlet_head, beacon_chain_out_ptr); + + // There is only one entry in the chainlet.. so the head and root are the same. + BOOST_CHECK(chainlet_root->m_hash == chainlet_head->m_hash); + BOOST_CHECK_EQUAL(beacon_chain_out_ptr->size(), 1); + } + + // Renewal + CTransaction tx3 {}; + tx3.nTime = int64_t {3}; + uint256 tx3_hash = tx3.GetHash(); + CBlockIndex index3 {}; + index3.nVersion = 13; + index3.nHeight = 3; + index3.nTime = tx3.nTime; + + GRC::Beacon beacon3 {TestKey::Public(), tx3.nTime, tx3_hash}; + beacon3.m_cpid = TestKey::Cpid(); + GRC::BeaconPayload beacon_payload3 {2, TestKey::Cpid(), beacon3}; + beacon_payload3.m_signature = TestKey::Signature(beacon_payload3); + + GRC::Contract contract3 = GRC::MakeContract(3, GRC::ContractAction::ADD, beacon_payload3); + GRC::ContractContext ctx3 {contract3, tx3, &index3}; + + registry.Add(ctx3); + + chainlet_head = registry.Try(TestKey::Cpid()); + + BOOST_CHECK(chainlet_head != nullptr); + + if (chainlet_head != nullptr) { + BOOST_CHECK(chainlet_head->m_hash == tx3_hash); + BOOST_CHECK(chainlet_head->m_status == GRC::BeaconStatusForStorage::RENEWAL); + + std::vector> beacon_chain_out {}; + + std::shared_ptr>> beacon_chain_out_ptr + = std::make_shared>>(beacon_chain_out); + + GRC::Beacon_ptr chainlet_root = registry.GetBeaconChainletRoot(chainlet_head, beacon_chain_out_ptr); + + BOOST_CHECK(chainlet_root->m_hash == activated_beacon_hash); + BOOST_CHECK_EQUAL(beacon_chain_out_ptr->size(), 2); + } + + // Second renewal + CTransaction tx4 {}; + tx4.nTime = int64_t {4}; + uint256 tx4_hash = tx4.GetHash(); + CBlockIndex index4 = {}; + index4.nVersion = 13; + index4.nHeight = 2; + index4.nTime = tx4.nTime; + + GRC::Beacon beacon4 {TestKey::Public(), tx4.nTime, tx4_hash}; + beacon4.m_cpid = TestKey::Cpid(); + GRC::BeaconPayload beacon_payload4 {2, TestKey::Cpid(), beacon4}; + beacon_payload4.m_signature = TestKey::Signature(beacon_payload4); + + GRC::Contract contract4 = GRC::MakeContract(3, GRC::ContractAction::ADD, beacon_payload4); + GRC::ContractContext ctx4 {contract4, tx4, &index4}; + registry.Add(ctx4); + + chainlet_head = registry.Try(TestKey::Cpid()); + + BOOST_CHECK(chainlet_head != nullptr); + + if (chainlet_head != nullptr) { + + std::vector> beacon_chain_out {}; + + std::shared_ptr>> beacon_chain_out_ptr + = std::make_shared>>(beacon_chain_out); + BOOST_CHECK(chainlet_head->m_hash == tx4_hash); + BOOST_CHECK(chainlet_head->m_status == GRC::BeaconStatusForStorage::RENEWAL); + + GRC::Beacon_ptr chainlet_root = registry.GetBeaconChainletRoot(chainlet_head, beacon_chain_out_ptr); + + BOOST_CHECK(chainlet_root->m_hash == activated_beacon_hash); + BOOST_CHECK_EQUAL(beacon_chain_out_ptr->size(), 3); + } + + // Let's corrupt the activation beacon to have a previous beacon hash that is the same as its hash... + bool original_activated_beacon_found = true; + bool circular_corruption_detected = false; + + if (GRC::Beacon_ptr first_active = registry.FindHistorical(activated_beacon_hash)) { + // The original activated beacon m_previous_hash should be the pending beacon hash (beacon1). + BOOST_CHECK(first_active->m_previous_hash == beacon1.m_hash); + BOOST_CHECK(first_active->m_status == GRC::BeaconStatusForStorage::ACTIVE); + + std::vector> beacon_chain_out {}; + + std::shared_ptr>> beacon_chain_out_ptr + = std::make_shared>>(beacon_chain_out); + + // This creates a immediately circular chainlet of one. + first_active->m_previous_hash = first_active->m_hash; + + beacon_chain_out_ptr->clear(); + + try { + GRC::Beacon_ptr chainlet_root = registry.GetBeaconChainletRoot(chainlet_head, beacon_chain_out_ptr); + } catch (std::runtime_error& e) { + circular_corruption_detected = true; + } + } else { + original_activated_beacon_found = false; + } + + BOOST_CHECK_EQUAL(original_activated_beacon_found, true); + + if (original_activated_beacon_found) { + BOOST_CHECK_EQUAL(circular_corruption_detected, true); + } +} + BOOST_AUTO_TEST_SUITE_END() From f8e3dab1299f67e4e1007ef8114eb83f99c85e23 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Fri, 2 Feb 2024 00:50:36 -0500 Subject: [PATCH 18/44] Corrections to GetBeaconChainletRoot from detailed unit testing --- src/gridcoin/beacon.cpp | 157 +++++++++++++++++++++++++++++++++------- 1 file changed, 129 insertions(+), 28 deletions(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index e1d8c7b464..e26ef16d3d 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -366,7 +366,7 @@ const BeaconOption BeaconRegistry::FindHistorical(const uint256& hash) return beacon_iter->second; } - return {}; + return nullptr; } bool BeaconRegistry::ContainsActive(const Cpid& cpid, const int64_t now) const @@ -800,20 +800,54 @@ int BeaconRegistry::GetDBHeight() Beacon_ptr BeaconRegistry::GetBeaconChainletRoot(Beacon_ptr beacon, std::shared_ptr>> beacon_chain_out) { - // Given that we have had rare situations where somehow cirularity has occurred in the beacon chainlet, which either + Cpid cpid = beacon->m_cpid; + + // The chain head itself. + auto beacon_iter = m_beacon_db.find(beacon->m_hash); + + if (beacon_iter == m_beacon_db.end()) { + // Beacon chainlet chainhead cannot be found. This is fatal. + + error("%s: Beacon chainlet is corrupted at chainhead for cpid %s: timestamp = %s" PRId64 ", ctx_hash = %s," + "prev_beacon_ctx_hash = %s, status = %s: not found in the registry.", + __func__, + beacon->m_cpid.ToString(), + beacon->m_timestamp, + beacon->m_hash.GetHex(), + beacon->m_previous_hash.GetHex(), + beacon->StatusToString()); + + std::string str_error = strprintf("ERROR: %s: Beacon chainlet is corrupted at chainhead for cpid %s: timestamp = %s" + PRId64 ", ctx_hash = %s, prev_beacon_ctx_hash = %s, status = %s: not found " + "in the registry.", + __func__, + beacon->m_cpid.ToString(), + beacon->m_timestamp, + beacon->m_hash.GetHex(), + beacon->m_previous_hash.GetHex(), + beacon->StatusToString()); + + Reset(); + + uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR); + + throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."}); + } + + // Given that we have had rare situations where somehow circularity has occurred in the beacon chainlet, which either // results in the current hash and previous hash being the same, or even suspected previous hash of another entry pointing - // back to a later beacon this vector is used to detect the circularity. + // back to a beacon in a circular manner, this vector is used to detect the circularity. std::vector encountered_hashes { beacon->m_hash }; - Cpid cpid = beacon->m_cpid; - if (beacon_chain_out != nullptr) { - LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: active beacon: timestamp = %" PRId64 ", ctx_hash = %s," - " prev_beacon_ctx_hash = %s", + LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: chainlet head beacon for cpid %s: timestamp = %" PRId64 ", ctx_hash = %s," + " prev_beacon_ctx_hash = %s, status = %s.", __func__, + beacon->m_cpid.ToString(), beacon->m_timestamp, beacon->m_hash.GetHex(), - beacon->m_previous_hash.GetHex()); + beacon->m_previous_hash.GetHex(), + beacon->StatusToString()); beacon_chain_out->push_back(std::make_pair(beacon->m_hash, beacon->m_timestamp)); } @@ -825,56 +859,123 @@ Beacon_ptr BeaconRegistry::GetBeaconChainletRoot(Beacon_ptr beacon, while (beacon->Renewed()) { - uint256 current_hash = beacon->m_hash; + // Select previous beacon in chainlet + auto beacon_iter = m_beacon_db.find(beacon->m_previous_hash); - beacon = m_beacon_db.find(beacon->m_previous_hash)->second; + if (beacon_iter == m_beacon_db.end()) { + // Linked beacon in chainlet cannot be found. This is fatal. - if (beacon_chain_out != nullptr) { - LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: renewal %u beacon: timestamp = %" PRId64 ", ctx_hash = %s," - " prev_beacon_ctx_hash = %s.", - __func__, - i, - beacon->m_timestamp, - beacon->m_hash.GetHex(), - beacon->m_previous_hash.GetHex()); + error("%s: Beacon chainlet is corrupted at %u links back for cpid %s: timestamp = %s" PRId64 ", ctx_hash = %s," + "prev_beacon_ctx_hash = %s, status = %s: prev_beacon not found in the registry.", + __func__, + i + 1, + beacon->m_cpid.ToString(), + beacon->m_timestamp, + beacon->m_hash.GetHex(), + beacon->m_previous_hash.GetHex(), + beacon->StatusToString()); + + std::string str_error = strprintf("ERROR: %s: Beacon chainlet is corrupted at %u links back for cpid %s: timestamp = %s" + PRId64 ", ctx_hash = %s, prev_beacon_ctx_hash = %s, status = %s: prev_beacon not found " + "in the registry.", + __func__, + i + 1, + beacon->m_cpid.ToString(), + beacon->m_timestamp, + beacon->m_hash.GetHex(), + beacon->m_previous_hash.GetHex(), + beacon->StatusToString()); - beacon_chain_out->push_back(std::make_pair(beacon->m_hash, beacon->m_timestamp)); + Reset(); + + uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR); + + throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."}); } - if (std::find(encountered_hashes.begin(), encountered_hashes.end(), beacon->m_hash) != encountered_hashes.end()) { + if (std::find(encountered_hashes.begin(), encountered_hashes.end(), beacon->m_previous_hash) != encountered_hashes.end()) { // If circularity is found this is an indication of corruption of beacon state and is fatal. // Produce an error message, reset the beacon registry, and require a restart of the node. + error("%s: Circularity encountered in beacon ownership chain for beacon with CPID %s, starting at hash %s, " "at %u linked entries back from the start, with offending hash %s.", __func__, cpid.ToString(), - current_hash.GetHex(), - i, - beacon->m_hash.GetHex()); + beacon->m_hash.GetHex(), + i + 1, + beacon->m_previous_hash.GetHex()); - std::string str_error = strprintf("ERROR %s: Circularity encountered in beacon ownership chain for beacon with CPID %s, " + std::string str_error = strprintf("ERROR: %s: Circularity encountered in beacon ownership chain for beacon with CPID %s, " "starting at hash %s, at %u linked entries back from the start, with offending hash %s.\n" "\n" "The client cannot continue and the beacon history has been reset and will be rebuilt " "on the next restart. Please restart Gridcoin.", __func__, cpid.ToString(), - encountered_hashes[0].GetHex(), - i, - beacon->m_hash.GetHex()); + beacon->m_hash.GetHex(), + i + 1, + beacon->m_previous_hash.GetHex()); Reset(); uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR); - throw std::runtime_error(std::string {"A fatal error has occurred and Gridcoin cannot continue. Please restart."}); + throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."}); } + // Reassign previous beacon to beacon. + beacon = beacon_iter->second; + encountered_hashes.push_back(beacon->m_hash); + if (beacon_chain_out != nullptr) { + LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: beacon %u links back for cpid %s: timestamp = %" PRId64 ", ctx_hash = %s," + " prev_beacon_ctx_hash = %s, status = %s.", + __func__, + i + 1, + beacon->m_cpid.ToString(), + beacon->m_timestamp, + beacon->m_hash.GetHex(), + beacon->m_previous_hash.GetHex(), + beacon->StatusToString()); + + beacon_chain_out->push_back(std::make_pair(beacon->m_hash, beacon->m_timestamp)); + } + ++i; } + // Check of initial advertised beacon's previous hash. + if (std::find(encountered_hashes.begin(), encountered_hashes.end(), beacon->m_previous_hash) != encountered_hashes.end()) { + // If circularity is found this is an indication of corruption of beacon state and is fatal. + // Produce an error message, reset the beacon registry, and require a restart of the node. + + error("%s: Circularity encountered in beacon ownership chain for beacon with CPID %s, starting at hash %s, " + "at %u linked entries back from the start, with offending hash %s.", + __func__, + cpid.ToString(), + beacon->m_hash.GetHex(), + i + 1, + beacon->m_previous_hash.GetHex()); + + std::string str_error = strprintf("ERROR: %s: Circularity encountered in beacon ownership chain for beacon with CPID %s, " + "starting at hash %s, at %u linked entries back from the start, with offending hash %s.\n" + "\n" + "The client cannot continue and the beacon history has been reset and will be rebuilt " + "on the next restart. Please restart Gridcoin.", + __func__, + cpid.ToString(), + beacon->m_hash.GetHex(), + i + 1, + beacon->m_previous_hash.GetHex()); + + Reset(); + + uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR); + + throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."}); + } + return beacon; } From 6616bcb443ef8f3cac85175698813b17076aabf0 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sat, 3 Feb 2024 11:55:05 -0500 Subject: [PATCH 19/44] Implement lambdas in GetBeaconChainletRoot to improve readability Also make a few other improvements, such as verification that the previous beacon to the original activated beacon has a status of pending. --- src/gridcoin/beacon.cpp | 186 +++++++++++++++------------------------- 1 file changed, 71 insertions(+), 115 deletions(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index e26ef16d3d..c7eb77127d 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -800,127 +800,100 @@ int BeaconRegistry::GetDBHeight() Beacon_ptr BeaconRegistry::GetBeaconChainletRoot(Beacon_ptr beacon, std::shared_ptr>> beacon_chain_out) { - Cpid cpid = beacon->m_cpid; - - // The chain head itself. - auto beacon_iter = m_beacon_db.find(beacon->m_hash); - - if (beacon_iter == m_beacon_db.end()) { - // Beacon chainlet chainhead cannot be found. This is fatal. - - error("%s: Beacon chainlet is corrupted at chainhead for cpid %s: timestamp = %s" PRId64 ", ctx_hash = %s," - "prev_beacon_ctx_hash = %s, status = %s: not found in the registry.", + const auto ChainletErrorHandle = [this](unsigned int i, Beacon_ptr beacon, std::string error_message) { + error("%s: Beacon chainlet is corrupted at link %u for cpid %s: timestamp = %s" PRId64 ", ctx_hash = %s," + "prev_beacon_ctx_hash = %s, status = %s: %s.", __func__, + i, beacon->m_cpid.ToString(), beacon->m_timestamp, beacon->m_hash.GetHex(), beacon->m_previous_hash.GetHex(), - beacon->StatusToString()); + beacon->StatusToString(), + error_message); - std::string str_error = strprintf("ERROR: %s: Beacon chainlet is corrupted at chainhead for cpid %s: timestamp = %s" - PRId64 ", ctx_hash = %s, prev_beacon_ctx_hash = %s, status = %s: not found " - "in the registry.", + std::string str_error = strprintf("ERROR: %s: Beacon chainlet is corrupted at link %u for cpid %s: timestamp = %s" + PRId64 ", ctx_hash = %s, prev_beacon_ctx_hash = %s, status = %s: %s.", __func__, + i, beacon->m_cpid.ToString(), beacon->m_timestamp, beacon->m_hash.GetHex(), beacon->m_previous_hash.GetHex(), - beacon->StatusToString()); + beacon->StatusToString(), + error_message); Reset(); uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR); - throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."}); - } - - // Given that we have had rare situations where somehow circularity has occurred in the beacon chainlet, which either - // results in the current hash and previous hash being the same, or even suspected previous hash of another entry pointing - // back to a beacon in a circular manner, this vector is used to detect the circularity. - std::vector encountered_hashes { beacon->m_hash }; + throw std::runtime_error(std::string {"The beacon registry is corrupted and will be rebuilt on the next start. " + "Please restart."}); + }; - if (beacon_chain_out != nullptr) { - LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: chainlet head beacon for cpid %s: timestamp = %" PRId64 ", ctx_hash = %s," + const auto ChainletLinkLog = [&beacon_chain_out](unsigned int i, Beacon_ptr beacon) { + LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: beacon chainlet link %u for cpid %s: timestamp = %" PRId64 ", ctx_hash = %s," " prev_beacon_ctx_hash = %s, status = %s.", __func__, + i, beacon->m_cpid.ToString(), beacon->m_timestamp, beacon->m_hash.GetHex(), beacon->m_previous_hash.GetHex(), beacon->StatusToString()); + if (beacon_chain_out == nullptr) { + return; + } + beacon_chain_out->push_back(std::make_pair(beacon->m_hash, beacon->m_timestamp)); + }; + + unsigned int i = 0; + + // Given that we have had rare situations where somehow circularity has occurred in the beacon chainlet, which either + // results in the current hash and previous hash being the same, or even suspected previous hash of another entry pointing + // back to a beacon in a circular manner, this vector is used to detect the circularity. + std::vector encountered_hashes; + + // The chain head itself. (This uses a scope to separate beacon_iter.) + { + auto beacon_iter = m_beacon_db.find(beacon->m_hash); + + if (beacon_iter == m_beacon_db.end()) { + // Beacon chainlet chainhead cannot be found. This is fatal. + ChainletErrorHandle(i, beacon, "not found in the registry"); + } + + // Make sure status is renewed or active. + if (beacon_iter->second->m_status != BeaconStatusForStorage::ACTIVE + && beacon_iter->second->m_status != BeaconStatusForStorage::RENEWAL) { + ChainletErrorHandle(i, beacon, "beacon status is not active or renewal"); + } + + encountered_hashes.push_back(beacon->m_hash); + + ChainletLinkLog(i, beacon); + + ++i; } // Walk back the entries in the historical beacon map linked by renewal prev tx hash until the first // beacon in the renewal chain is found (the original advertisement). The accrual starts no earlier // than here. - unsigned int i = 0; - while (beacon->Renewed()) { // Select previous beacon in chainlet auto beacon_iter = m_beacon_db.find(beacon->m_previous_hash); if (beacon_iter == m_beacon_db.end()) { - // Linked beacon in chainlet cannot be found. This is fatal. - - error("%s: Beacon chainlet is corrupted at %u links back for cpid %s: timestamp = %s" PRId64 ", ctx_hash = %s," - "prev_beacon_ctx_hash = %s, status = %s: prev_beacon not found in the registry.", - __func__, - i + 1, - beacon->m_cpid.ToString(), - beacon->m_timestamp, - beacon->m_hash.GetHex(), - beacon->m_previous_hash.GetHex(), - beacon->StatusToString()); - - std::string str_error = strprintf("ERROR: %s: Beacon chainlet is corrupted at %u links back for cpid %s: timestamp = %s" - PRId64 ", ctx_hash = %s, prev_beacon_ctx_hash = %s, status = %s: prev_beacon not found " - "in the registry.", - __func__, - i + 1, - beacon->m_cpid.ToString(), - beacon->m_timestamp, - beacon->m_hash.GetHex(), - beacon->m_previous_hash.GetHex(), - beacon->StatusToString()); - - Reset(); - - uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR); - - throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."}); + ChainletErrorHandle(i, beacon, "previous beacon not found in the registry"); } if (std::find(encountered_hashes.begin(), encountered_hashes.end(), beacon->m_previous_hash) != encountered_hashes.end()) { // If circularity is found this is an indication of corruption of beacon state and is fatal. // Produce an error message, reset the beacon registry, and require a restart of the node. - - error("%s: Circularity encountered in beacon ownership chain for beacon with CPID %s, starting at hash %s, " - "at %u linked entries back from the start, with offending hash %s.", - __func__, - cpid.ToString(), - beacon->m_hash.GetHex(), - i + 1, - beacon->m_previous_hash.GetHex()); - - std::string str_error = strprintf("ERROR: %s: Circularity encountered in beacon ownership chain for beacon with CPID %s, " - "starting at hash %s, at %u linked entries back from the start, with offending hash %s.\n" - "\n" - "The client cannot continue and the beacon history has been reset and will be rebuilt " - "on the next restart. Please restart Gridcoin.", - __func__, - cpid.ToString(), - beacon->m_hash.GetHex(), - i + 1, - beacon->m_previous_hash.GetHex()); - - Reset(); - - uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR); - - throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."}); + ChainletErrorHandle(i, beacon, "circularity encountered"); } // Reassign previous beacon to beacon. @@ -929,51 +902,34 @@ Beacon_ptr BeaconRegistry::GetBeaconChainletRoot(Beacon_ptr beacon, encountered_hashes.push_back(beacon->m_hash); if (beacon_chain_out != nullptr) { - LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: beacon %u links back for cpid %s: timestamp = %" PRId64 ", ctx_hash = %s," - " prev_beacon_ctx_hash = %s, status = %s.", - __func__, - i + 1, - beacon->m_cpid.ToString(), - beacon->m_timestamp, - beacon->m_hash.GetHex(), - beacon->m_previous_hash.GetHex(), - beacon->StatusToString()); - - beacon_chain_out->push_back(std::make_pair(beacon->m_hash, beacon->m_timestamp)); + ChainletLinkLog(i, beacon); } ++i; } - // Check of initial advertised beacon's previous hash. - if (std::find(encountered_hashes.begin(), encountered_hashes.end(), beacon->m_previous_hash) != encountered_hashes.end()) { - // If circularity is found this is an indication of corruption of beacon state and is fatal. - // Produce an error message, reset the beacon registry, and require a restart of the node. + // Check of initial advertised beacon's previous hash. This should point to the pending beacon that was activated and not + // anywhere else. + { + // Select previous beacon in chainlet + auto beacon_iter = m_beacon_db.find(beacon->m_previous_hash); - error("%s: Circularity encountered in beacon ownership chain for beacon with CPID %s, starting at hash %s, " - "at %u linked entries back from the start, with offending hash %s.", - __func__, - cpid.ToString(), - beacon->m_hash.GetHex(), - i + 1, - beacon->m_previous_hash.GetHex()); - - std::string str_error = strprintf("ERROR: %s: Circularity encountered in beacon ownership chain for beacon with CPID %s, " - "starting at hash %s, at %u linked entries back from the start, with offending hash %s.\n" - "\n" - "The client cannot continue and the beacon history has been reset and will be rebuilt " - "on the next restart. Please restart Gridcoin.", - __func__, - cpid.ToString(), - beacon->m_hash.GetHex(), - i + 1, - beacon->m_previous_hash.GetHex()); + if (beacon_iter == m_beacon_db.end()) { + ChainletErrorHandle(i, beacon, "previous beacon not found in the registry"); + } - Reset(); + // Make sure status of previous beacon is pending. + if (beacon_iter->second->m_status != BeaconStatusForStorage::PENDING) { + ChainletErrorHandle(i, beacon, "previous beacon to the beacon marked active is not pending"); + } - uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR); + if (std::find(encountered_hashes.begin(), encountered_hashes.end(), beacon->m_previous_hash) != encountered_hashes.end()) { + // If circularity is found this is an indication of corruption of beacon state and is fatal. + // Produce an error message, reset the beacon registry, and require a restart of the node. + ChainletErrorHandle(i, beacon, "circularity encountered"); + } - throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."}); + // Note that we do not actually walk back to the pending beacon. The parameter beacon remains at the activated beacon. } return beacon; From 7cfaa0197662e241d8bb0a8c7c0a6fa0e4f8de7d Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sat, 10 Feb 2024 20:13:55 -0500 Subject: [PATCH 20/44] Add try/catch around calls to GetBeaconChainletRoot The catch for std::runtime_exception in the Tally code will cause a std::abort(). The RPC code will throw a RPC_INTERNAL_ERROR. --- src/gridcoin/tally.cpp | 6 +++++- src/rpc/mining.cpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/gridcoin/tally.cpp b/src/gridcoin/tally.cpp index 024745761f..0f92700364 100644 --- a/src/gridcoin/tally.cpp +++ b/src/gridcoin/tally.cpp @@ -1233,7 +1233,11 @@ CAmount Tally::GetNewbieSuperblockAccrualCorrection(const Cpid& cpid, const Supe // Walk back the entries in the historical beacon map linked by renewal prev tx hash until the first // beacon in the renewal chain is found (the original advertisement). The accrual starts no earlier // than here. - beacon_ptr = beacons.GetBeaconChainletRoot(beacon); + try { + beacon_ptr = beacons.GetBeaconChainletRoot(beacon); + } catch (std::runtime_error& e) { + std::abort(); + } const CBlockIndex* pindex_baseline = GRC::Tally::GetBaseline(); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index e266f624cf..be24b0b100 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -307,7 +307,11 @@ UniValue auditsnapshotaccrual(const UniValue& params, bool fHelp) UniValue beacon_chain(UniValue::VARR); - beacon_ptr = beacons.GetBeaconChainletRoot(beacon_ptr, beacon_chain_out_ptr); + try { + beacon_ptr = beacons.GetBeaconChainletRoot(beacon_ptr, beacon_chain_out_ptr); + } catch (std::runtime_error& e) { + throw JSONRPCError(RPC_INTERNAL_ERROR, e.what()); + } for (const auto& iter : *beacon_chain_out_ptr) { UniValue beacon_chain_entry(UniValue::VOBJ); From bad19c523b78ea9c3223dee82e4a4feab229a7e7 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sat, 3 Feb 2024 17:33:46 -0500 Subject: [PATCH 21/44] Linter spellcheck corrections --- src/gridcoin/beacon.cpp | 2 +- src/gridcoin/contract/registry_db.h | 4 ++-- src/gridcoin/md5.c | 8 ++++---- src/gridcoin/quorum.cpp | 2 +- src/gridcoin/scraper/scraper.cpp | 2 +- src/gridcoin/sidestake.h | 2 +- src/miner.cpp | 2 +- src/qt/transactiontablemodel.cpp | 2 +- src/random.h | 2 +- src/script.cpp | 2 +- src/test/dos_tests.cpp | 2 +- src/test/script_tests.cpp | 2 +- src/test/xxd/xxd.c | 2 +- src/util.h | 2 +- test/lint/lint-spelling.ignore-words.txt | 1 + 15 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index c7eb77127d..e529fdff07 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -1313,7 +1313,7 @@ template<> void BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries(GRC::Be } if (entry.m_status == BeaconStatusForStorage::ACTIVE) { - // Note that in the orginal activation, all the activations happen for a superblock, and then the expired_entry set is + // Note that in the original activation, all the activations happen for a superblock, and then the expired_entry set is // cleared and then new expired entries recorded from the just committed SB. This method operates at the record level, but // clearing the expired_entries for each ACTIVE record posting will achieve the same effect, because the entries are ordered // the proper way. It is a little bit of undesired work, but it is not worth the complexity of feeding the boundaries diff --git a/src/gridcoin/contract/registry_db.h b/src/gridcoin/contract/registry_db.h index 804c9a6f8a..41f37e2627 100644 --- a/src/gridcoin/contract/registry_db.h +++ b/src/gridcoin/contract/registry_db.h @@ -64,7 +64,7 @@ class RegistryDB //! \param entries The map of current entries. //! \param pending_entries. The map of pending entries. This is not used in the general template, only in the beacons //! specialization. - //! \param expired_entries. The map of expired pending entries. This is not used in the geenral template, only in the + //! \param expired_entries. The map of expired pending entries. This is not used in the general template, only in the //! beacons specialization. //! //! \return block height up to and including which the entry records were stored. @@ -230,7 +230,7 @@ class RegistryDB } //! - //! \brief Handles the passivation of previous historical entries that have been superceded by current entries. + //! \brief Handles the passivation of previous historical entries that have been superseded by current entries. //! //! \param historical_entry_ptr. Shared smart pointer to current historical entry already inserted into historical map. //! diff --git a/src/gridcoin/md5.c b/src/gridcoin/md5.c index 18a0923825..65ccee979f 100644 --- a/src/gridcoin/md5.c +++ b/src/gridcoin/md5.c @@ -6,7 +6,7 @@ * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions + * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms @@ -31,7 +31,7 @@ * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library + * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: @@ -49,7 +49,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * The licence and distribution terms for any publically available version or + * The licence and distribution terms for any publicly available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ @@ -244,7 +244,7 @@ uint8_t *GRC__MD5(const uint8_t *data, size_t len, uint8_t out[MD5_DIGEST_LENGTH // As pointed out by Wei Dai , the above can be // simplified to the code below. Wei attributes these optimizations -// to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. +// to Peter Gutmann's SSH code, and he attributes it to Rich Schroeppel. #define F(b, c, d) ((((c) ^ (d)) & (b)) ^ (d)) #define G(b, c, d) ((((b) ^ (c)) & (d)) ^ (c)) #define H(b, c, d) ((b) ^ (c) ^ (d)) diff --git a/src/gridcoin/quorum.cpp b/src/gridcoin/quorum.cpp index 92cd83f0f5..c0d04a4753 100644 --- a/src/gridcoin/quorum.cpp +++ b/src/gridcoin/quorum.cpp @@ -721,7 +721,7 @@ class SuperblockValidator std::vector m_resolved_parts; //! - //! \brief Divisor set by the \c ProjectCombiner for iteraton over each + //! \brief Divisor set by the \c ProjectCombiner for iteration over each //! convergence combination. //! size_t m_combiner_mask; diff --git a/src/gridcoin/scraper/scraper.cpp b/src/gridcoin/scraper/scraper.cpp index 95788b33e6..9a65484b78 100755 --- a/src/gridcoin/scraper/scraper.cpp +++ b/src/gridcoin/scraper/scraper.cpp @@ -208,7 +208,7 @@ std::map> CScraperManifest::mapManife ConvergedScraperStats ConvergedScraperStatsCache GUARDED_BY(cs_ConvergedScraperStatsCache) = {}; /** - * @brief Scraper loggger function + * @brief Scraper logger function * @param eType * @param sCall * @param sMessage diff --git a/src/gridcoin/sidestake.h b/src/gridcoin/sidestake.h index d318fe8043..6b001e412d 100644 --- a/src/gridcoin/sidestake.h +++ b/src/gridcoin/sidestake.h @@ -45,7 +45,7 @@ class Allocation : public Fraction //! //! \brief Allocations extend the Fraction class and can also represent the result of the allocation constructed fraction - //! and the result of the muliplication of that fraction times the reward, which is in CAmount (i.e. int64_t). + //! and the result of the multiplication of that fraction times the reward, which is in CAmount (i.e. int64_t). //! //! \return CAmount of the Fraction representation of the actual allocation. //! diff --git a/src/miner.cpp b/src/miner.cpp index 1c45764078..c95c3ffe02 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -939,7 +939,7 @@ void SplitCoinStakeOutput(CBlock &blocknew, int64_t &nReward, bool &fEnableStake CScript SideStakeScriptPubKey; GRC::Allocation SumAllocation; - // Lambda for sidestake allocation. This iterates throught the provided sidestake vector until either all elements processed, + // Lambda for sidestake allocation. This iterates through the provided sidestake vector until either all elements processed, // the maximum number of sidestake outputs is reached via the provided output_limit, or accumulated allocation will exceed 100%. const auto allocate_sidestakes = [&](SideStakeAlloc sidestakes, unsigned int output_limit) { for (auto iterSideStake = sidestakes.begin(); diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 7a58dff1ee..48b26bdbaf 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -216,7 +216,7 @@ class TransactionTablePriv // // If a status update is needed (blocks came in since last check), // update the status of this transaction from the wallet. Otherwise, - // simply re-use the cached status. + // simply reuse the cached status. TRY_LOCK(cs_main, lockMain); if(lockMain) { diff --git a/src/random.h b/src/random.h index 821927af92..066ad1e68f 100644 --- a/src/random.h +++ b/src/random.h @@ -100,7 +100,7 @@ constexpr auto GetRandMillis = GetRandomDuration; * is memoryless and should be used for repeated network events (e.g. sending a * certain type of message) to minimize leaking information to observers. * - * The probability of an event occuring before time x is 1 - e^-(x/a) where a + * The probability of an event occurring before time x is 1 - e^-(x/a) where a * is the average interval between events. * */ std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval); diff --git a/src/script.cpp b/src/script.cpp index 45d5e9000f..e81af2bfcf 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1102,7 +1102,7 @@ class CSignatureCache { // Evict a random entry. Random because that helps // foil would-be DoS attackers who might try to pre-generate - // and re-use a set of valid signatures just-slightly-greater + // and reuse a set of valid signatures just-slightly-greater // than our cache size. uint256 randomHash = GetRandHash(); std::vector unused; diff --git a/src/test/dos_tests.cpp b/src/test/dos_tests.cpp index ff7ec22e75..82653c0632 100755 --- a/src/test/dos_tests.cpp +++ b/src/test/dos_tests.cpp @@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) tx.vin[j].prevout.hash = txPrev.GetHash(); } BOOST_CHECK(SignSignature(keystore, txPrev, tx, 0)); - // Re-use same signature for other inputs + // Reuse same signature for other inputs // (they don't have to be valid for this test) for (unsigned int j = 1; j < tx.vin.size(); j++) tx.vin[j].scriptSig = tx.vin[0].scriptSig; diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 2a35324da8..9711966abd 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -282,7 +282,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, 0)); keys.clear(); - keys.push_back(key2); keys.push_back(key2); // Can't re-use sig + keys.push_back(key2); keys.push_back(key2); // Can't reuse sig CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23); BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, 0)); diff --git a/src/test/xxd/xxd.c b/src/test/xxd/xxd.c index e2fc9dff6a..ae25feed2b 100644 --- a/src/test/xxd/xxd.c +++ b/src/test/xxd/xxd.c @@ -36,7 +36,7 @@ * 7.06.96 -i printed 'int' instead of 'char'. *blush* * added Bram's OS2 ifdefs... * 18.07.96 gcc -Wall @ SunOS4 is now silent. - * Added osver for MSDOS/DJGPP/WIN32. + * Added osver for MS-DOS/DJGPP/WIN32. * 29.08.96 Added size_t to strncmp() for Amiga. * 24.03.97 Windows NT support (Phil Hanna). Clean exit for Amiga WB (Bram) * 02.04.97 Added -E option, to have EBCDIC translation instead of ASCII diff --git a/src/util.h b/src/util.h index 66288783ad..511c828155 100644 --- a/src/util.h +++ b/src/util.h @@ -168,7 +168,7 @@ inline int64_t abs64(int64_t n) //! implementations. //! //! In particular this class is used for sidestake allocations, both the allocation "percentage", and the CAmount allocations -//! resulting from muliplying the allocation (fraction) times the CAmount rewards. +//! resulting from multiplying the allocation (fraction) times the CAmount rewards. //! class Fraction { public: diff --git a/test/lint/lint-spelling.ignore-words.txt b/test/lint/lint-spelling.ignore-words.txt index 9cbee6e709..4529488a77 100644 --- a/test/lint/lint-spelling.ignore-words.txt +++ b/test/lint/lint-spelling.ignore-words.txt @@ -27,3 +27,4 @@ smoe sur clen siz +anull From dd8a519a6b8848455701cd542dfaaac2244f7fa3 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 4 Feb 2024 12:47:36 -0500 Subject: [PATCH 22/44] Miscellaneous minor fixes to correct compilation warnings --- src/qt/voting/polltablemodel.cpp | 2 -- src/qt/voting/polltablemodel.h | 2 -- src/rpc/blockchain.cpp | 2 +- src/wallet/rpcwallet.cpp | 15 ++++++++------- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/qt/voting/polltablemodel.cpp b/src/qt/voting/polltablemodel.cpp index 8f4a467c8e..5cfc9f3678 100644 --- a/src/qt/voting/polltablemodel.cpp +++ b/src/qt/voting/polltablemodel.cpp @@ -15,7 +15,6 @@ using namespace GRC; -namespace { PollTableDataModel::PollTableDataModel() { qRegisterMetaType>(); @@ -189,7 +188,6 @@ void PollTableDataModel::handlePollStaleFlag(QString poll_txid_string) emit layoutChanged(); } -} // Anonymous namespace // ----------------------------------------------------------------------------- // Class: PollTableModel diff --git a/src/qt/voting/polltablemodel.h b/src/qt/voting/polltablemodel.h index 5f3b1ac406..daffadb170 100644 --- a/src/qt/voting/polltablemodel.h +++ b/src/qt/voting/polltablemodel.h @@ -15,7 +15,6 @@ class PollItem; class VotingModel; -namespace { class PollTableDataModel : public QAbstractTableModel { public: @@ -35,7 +34,6 @@ class PollTableDataModel : public QAbstractTableModel std::vector m_rows; }; -} // Anonymous namespace class PollTableModel : public QSortFilterProxyModel { diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 5adab057b5..8c3964a9a4 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1750,7 +1750,7 @@ UniValue beaconstatus(const UniValue& params, bool fHelp) active.push_back(entry); } - for (auto beacon_ptr : beacons.FindPending(*cpid)) { + for (const auto& beacon_ptr : beacons.FindPending(*cpid)) { UniValue entry(UniValue::VOBJ); entry.pushKV("cpid", cpid->ToString()); entry.pushKV("active", false); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0a9e78857a..17b5b96fe4 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2188,11 +2188,10 @@ UniValue walletpassphrase(const UniValue& params, bool fHelp) strWalletPass.reserve(100); strWalletPass = std::string_view{params[0].get_str()}; - if (strWalletPass.length() > 0) - { + if (strWalletPass.length() > 0) { LOCK2(cs_main, pwalletMain->cs_wallet); - if (!pwalletMain->Unlock(strWalletPass)) + if (!pwalletMain->Unlock(strWalletPass)) { // Check if the passphrase has a null character if (strWalletPass.find('\0') == std::string::npos) { throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect."); @@ -2204,11 +2203,12 @@ UniValue walletpassphrase(const UniValue& params, bool fHelp) "the first null character. If this is successful, please set a new " "passphrase to avoid this issue in the future."); } - } - else + } + } else { throw runtime_error( "walletpassphrase \n" "Stores the wallet decryption key in memory for seconds."); + } NewThread(ThreadTopUpKeyPool, nullptr); int64_t* pnSleepTime = new int64_t(nSleepTime); @@ -2252,7 +2252,7 @@ UniValue walletpassphrasechange(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) + if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) { // Check if the old passphrase had a null character if (strOldWalletPass.find('\0') == std::string::npos) { throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect."); @@ -2263,12 +2263,13 @@ UniValue walletpassphrasechange(const UniValue& params, bool fHelp) "please try again with only the characters up to — but not including — " "the first null character."); } + } return NullUniValue; } /** - * Run the walled diagnose checks + * Run the wallet diagnose checks */ UniValue walletdiagnose(const UniValue& params, bool fHelp) { From 2acae308586e51eb3284790699a19b9938243b5d Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 4 Feb 2024 12:54:50 -0500 Subject: [PATCH 23/44] Fix CURLINFO_SPEED_DOWNLOAD deprecation warning. --- src/gridcoin/scraper/http.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gridcoin/scraper/http.cpp b/src/gridcoin/scraper/http.cpp index 149fc5a511..022aafe176 100644 --- a/src/gridcoin/scraper/http.cpp +++ b/src/gridcoin/scraper/http.cpp @@ -98,10 +98,18 @@ namespace { pg->lastruntime = currenttime; +#if LIBCURL_VERSION_NUM >= 0x073700 + curl_off_t speed; +#else double speed; +#endif CURLcode result; +#if LIBCURL_VERSION_NUM >= 0x073700 + result = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD_T, &speed); +#else result = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &speed); +#endif // Download speed update if (result == CURLE_OK) From fa50878ae29dd7964fab73cc9189e0e573176fc7 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 4 Feb 2024 13:07:25 -0500 Subject: [PATCH 24/44] Remove unused mock contract function in project tests --- src/test/gridcoin/project_tests.cpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/test/gridcoin/project_tests.cpp b/src/test/gridcoin/project_tests.cpp index 66fabbd723..900ae1babe 100644 --- a/src/test/gridcoin/project_tests.cpp +++ b/src/test/gridcoin/project_tests.cpp @@ -9,25 +9,6 @@ #include namespace { -//! -//! \brief Generate a mock project contract. -//! -//! \param key A fake project name as it might appear in a contract. -//! \param value A fake project URL as it might appear in a contract. -//! -//! \return A mock project contract. -//! -GRC::Contract contract(std::string key, std::string value) -{ - return GRC::MakeContract( - // Add or delete checked before passing to handler, so we don't need - // to give a specific value here: - GRC::ContractAction::UNKNOWN, - std::move(key), - std::move(value), - 1234567); // timestamp -} - void AddProjectEntry(const uint32_t& payload_version, const std::string& name, const std::string& url, const bool& gdpr_status, const int& height, const uint64_t time, const bool& reset_registry = false) { From b1b6035b7e11aae9a57fd37e14739a99bc192b1c Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 4 Feb 2024 16:07:45 -0500 Subject: [PATCH 25/44] Change sort to custom_sort to suppress overloaded virtual warning --- src/qt/voting/additionalfieldstablemodel.cpp | 2 +- src/qt/voting/additionalfieldstablemodel.h | 2 +- src/qt/voting/polltab.cpp | 2 +- src/qt/voting/polltablemodel.cpp | 2 +- src/qt/voting/polltablemodel.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/qt/voting/additionalfieldstablemodel.cpp b/src/qt/voting/additionalfieldstablemodel.cpp index a8f8148fa6..85f99cb639 100644 --- a/src/qt/voting/additionalfieldstablemodel.cpp +++ b/src/qt/voting/additionalfieldstablemodel.cpp @@ -177,7 +177,7 @@ void AdditionalFieldsTableModel::refresh() ->reload(additional_fields); } -Qt::SortOrder AdditionalFieldsTableModel::sort(int column) +Qt::SortOrder AdditionalFieldsTableModel::custom_sort(int column) { if (sortColumn() == column) { QSortFilterProxyModel::sort(column, static_cast(!sortOrder())); diff --git a/src/qt/voting/additionalfieldstablemodel.h b/src/qt/voting/additionalfieldstablemodel.h index 596db7ef53..40cd3703dd 100644 --- a/src/qt/voting/additionalfieldstablemodel.h +++ b/src/qt/voting/additionalfieldstablemodel.h @@ -42,7 +42,7 @@ class AdditionalFieldsTableModel : public QSortFilterProxyModel public slots: void refresh(); - Qt::SortOrder sort(int column); + Qt::SortOrder custom_sort(int column); private: const PollItem* m_poll_item; diff --git a/src/qt/voting/polltab.cpp b/src/qt/voting/polltab.cpp index 672ab759ac..46f09e9708 100644 --- a/src/qt/voting/polltab.cpp +++ b/src/qt/voting/polltab.cpp @@ -205,7 +205,7 @@ void PollTab::filter(const QString& needle) void PollTab::sort(const int column) { - const Qt::SortOrder order = m_polltable_model->sort(column); + const Qt::SortOrder order = m_polltable_model->custom_sort(column); ui->table->horizontalHeader()->setSortIndicator(column, order); } diff --git a/src/qt/voting/polltablemodel.cpp b/src/qt/voting/polltablemodel.cpp index 5cfc9f3678..880dcf71f1 100644 --- a/src/qt/voting/polltablemodel.cpp +++ b/src/qt/voting/polltablemodel.cpp @@ -292,7 +292,7 @@ void PollTableModel::changeTitleFilter(const QString& pattern) emit layoutChanged(); } -Qt::SortOrder PollTableModel::sort(int column) +Qt::SortOrder PollTableModel::custom_sort(int column) { if (sortColumn() == column) { QSortFilterProxyModel::sort(column, static_cast(!sortOrder())); diff --git a/src/qt/voting/polltablemodel.h b/src/qt/voting/polltablemodel.h index daffadb170..eecf65f5f4 100644 --- a/src/qt/voting/polltablemodel.h +++ b/src/qt/voting/polltablemodel.h @@ -78,7 +78,7 @@ class PollTableModel : public QSortFilterProxyModel public slots: void refresh(); void changeTitleFilter(const QString& pattern); - Qt::SortOrder sort(int column); + Qt::SortOrder custom_sort(int column); void handlePollStaleFlag(QString poll_txid_string); From b7854b59a7a66fcbf58421140df244e482947cf8 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 4 Feb 2024 16:39:39 -0500 Subject: [PATCH 26/44] Eliminate infinite recursion warning in UnlockContext --- src/qt/walletmodel.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 7cb909d00b..6c25237a13 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -107,7 +107,10 @@ class WalletModel : public QObject // Copy operator and constructor transfer the context UnlockContext(const UnlockContext& obj) { CopyFrom(obj); } - UnlockContext& operator=(const UnlockContext& rhs) { CopyFrom(rhs); return *this; } + + // Commented out as we don't use the below form and it triggers an infinite recursion + // warning. + // UnlockContext& operator=(const UnlockContext& rhs) { CopyFrom(rhs); return *this; } private: WalletModel *wallet; bool valid; From de7507b3a5696df68b9f00305ba9c46fc5f4a12b Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 4 Feb 2024 17:14:03 -0500 Subject: [PATCH 27/44] Remove unnecessary move() calls. --- src/gridcoin/voting/builders.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/gridcoin/voting/builders.cpp b/src/gridcoin/voting/builders.cpp index 0bd2597c70..676316d3f1 100644 --- a/src/gridcoin/voting/builders.cpp +++ b/src/gridcoin/voting/builders.cpp @@ -1020,7 +1020,7 @@ PollBuilder PollBuilder::SetTitle(std::string title) ToString(Poll::MAX_TITLE_SIZE))); } - m_poll->m_title = std::move(title); + m_poll->m_title = title; return std::move(*this); } @@ -1037,7 +1037,7 @@ PollBuilder PollBuilder::SetUrl(std::string url) ToString(Poll::MAX_URL_SIZE))); } - m_poll->m_url = std::move(url); + m_poll->m_url = url; return std::move(*this); } @@ -1050,7 +1050,7 @@ PollBuilder PollBuilder::SetQuestion(std::string question) ToString(Poll::MAX_QUESTION_SIZE))); } - m_poll->m_question = std::move(question); + m_poll->m_question = question; return std::move(*this); } @@ -1059,13 +1059,13 @@ PollBuilder PollBuilder::SetChoices(std::vector labels) { m_poll->m_choices = Poll::ChoiceList(); - return AddChoices(std::move(labels)); + return AddChoices(labels); } PollBuilder PollBuilder::AddChoices(std::vector labels) { for (auto& label : labels) { - *this = AddChoice(std::move(label)); + *this = AddChoice(label); } return std::move(*this); @@ -1096,7 +1096,7 @@ PollBuilder PollBuilder::AddChoice(std::string label) throw VotingError(strprintf(_("Duplicate poll choice: %s"), label)); } - m_poll->m_choices.Add(std::move(label)); + m_poll->m_choices.Add(label); return std::move(*this); } @@ -1105,20 +1105,20 @@ PollBuilder PollBuilder::SetAdditionalFields(std::vector { m_poll->m_additional_fields = Poll::AdditionalFieldList(); - return AddAdditionalFields(std::move(fields)); + return AddAdditionalFields(fields); } PollBuilder PollBuilder::SetAdditionalFields(Poll::AdditionalFieldList fields) { m_poll->m_additional_fields = Poll::AdditionalFieldList(); - return AddAdditionalFields(std::move(fields)); + return AddAdditionalFields(fields); } PollBuilder PollBuilder::AddAdditionalFields(std::vector fields) { for (auto& field : fields) { - *this = AddAdditionalField(std::move(field)); + *this = AddAdditionalField(field); } if (!m_poll->m_additional_fields.WellFormed(m_poll->m_type.Value())) { @@ -1131,7 +1131,7 @@ PollBuilder PollBuilder::AddAdditionalFields(std::vector PollBuilder PollBuilder::AddAdditionalFields(Poll::AdditionalFieldList fields) { for (auto& field : fields) { - *this = AddAdditionalField(std::move(field)); + *this = AddAdditionalField(field); } if (!m_poll->m_additional_fields.WellFormed(m_poll->m_type.Value())) { @@ -1177,7 +1177,7 @@ PollBuilder PollBuilder::AddAdditionalField(Poll::AdditionalField field) throw VotingError(strprintf(_("Duplicate poll additional field: %s"), field.m_name)); } - m_poll->m_additional_fields.Add(std::move(field)); + m_poll->m_additional_fields.Add(field); return std::move(*this); } From 0db3e70735c39ed5d14d04b768bfbd5a877d4dfd Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 4 Feb 2024 17:14:29 -0500 Subject: [PATCH 28/44] Eliminate potential dangling temporary reference warning --- src/gridcoin/gridcoin.cpp | 4 ++-- src/rpc/client.cpp | 4 ++-- src/rpc/rawtransaction.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gridcoin/gridcoin.cpp b/src/gridcoin/gridcoin.cpp index 5ef78ce340..39853e113f 100644 --- a/src/gridcoin/gridcoin.cpp +++ b/src/gridcoin/gridcoin.cpp @@ -214,8 +214,8 @@ void InitializeContracts(CBlockIndex* pindexBest) // for polls and votes. The reason for this is quite simple. Polls and votes are UNIQUE. The reversion of an add // is simply to delete them. The wallet startup replay requirement is still required for polls and votes, because // the Poll/Vote classes do not have a backing registry db yet. - const int& start_height = std::min(std::max(db_heights.GetLowestRegistryBlockHeight(), V11_height), - lookback_window_low_height); + int start_height = std::min(std::max(db_heights.GetLowestRegistryBlockHeight(), V11_height), + lookback_window_low_height); LogPrintf("Gridcoin: Starting contract replay from height %i.", start_height); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index b1a76da8f8..9724c04aa9 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -352,8 +352,8 @@ int CommandLineRPC(int argc, char *argv[]) const UniValue reply = CallRPC(strMethod, params); // Parse reply - const UniValue& result = find_value(reply, "result"); - const UniValue& error = find_value(reply, "error"); + UniValue result = find_value(reply, "result"); + UniValue error = find_value(reply, "error"); if (!error.isNull()) { diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index d3688e459b..ef570f9da7 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1528,14 +1528,14 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) const UniValue& input = inputs[idx]; const UniValue& o = input.get_obj(); - const UniValue& txid_v = find_value(o, "txid"); + UniValue txid_v = find_value(o, "txid"); if (!txid_v.isStr()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing txid key"); string txid = txid_v.get_str(); if (!IsHex(txid)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid"); - const UniValue& vout_v = find_value(o, "vout"); + UniValue vout_v = find_value(o, "vout"); if (!vout_v.isNum()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key"); int nOutput = vout_v.get_int(); From 326690849457a1b6fdea2d475c5edb5844905aa1 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 4 Feb 2024 22:31:39 -0500 Subject: [PATCH 29/44] Add IsMine log for voting contract txs with logging category vote --- src/gridcoin/mrc.cpp | 2 -- src/gridcoin/voting/result.cpp | 7 +++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gridcoin/mrc.cpp b/src/gridcoin/mrc.cpp index e3db165ad7..ef8fcc7205 100644 --- a/src/gridcoin/mrc.cpp +++ b/src/gridcoin/mrc.cpp @@ -280,8 +280,6 @@ bool TrySignMRC( CBlockIndex* pindex, GRC::MRC& mrc) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { - AssertLockHeld(cs_main); - // lock needs to be taken on pwallet here. LOCK(pwallet->cs_wallet); diff --git a/src/gridcoin/voting/result.cpp b/src/gridcoin/voting/result.cpp index 95f0be85fe..962cf21303 100644 --- a/src/gridcoin/voting/result.cpp +++ b/src/gridcoin/voting/result.cpp @@ -109,6 +109,11 @@ class VoteCandidate { LOCK(pwalletMain->cs_wallet); + LogPrint(BCLog::LogFlags::VOTE, "INFO: %s: vote contract tx hash %s ismine status %i", + __func__, + m_tx.GetHash().GetHex(), + pwalletMain->IsMine(m_tx)); + return pwalletMain->IsMine(m_tx); } @@ -1256,6 +1261,7 @@ void PollResult::TallyVote(VoteDetail detail) if (detail.m_ismine != ISMINE_NO) { bool choice_found = false; + // If the response offset entry already exists, then append to the existing entry... for (auto& choice : m_self_vote_detail.m_responses) { if (choice.first == response_offset) { choice.second += response_weight; @@ -1264,6 +1270,7 @@ void PollResult::TallyVote(VoteDetail detail) } } + // Otherwise make a new m_responses entry to represent the response offset and the associated weight. if (!choice_found) { m_self_vote_detail.m_responses.push_back(std::make_pair(response_offset, response_weight)); } From d7b2d97b6ed95c511c54dfba298d39656ca40f96 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 4 Feb 2024 22:58:31 -0500 Subject: [PATCH 30/44] Change fFlushOnClose to flush_on_close to eliminate shadowed member warning on Clang --- src/wallet/walletdb.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 83300f9641..3e35ccf163 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -99,7 +99,8 @@ class CKeyMetadata class CWalletDB : public CDB { public: - CWalletDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnClose = true) : CDB(strFilename, pszMode, fFlushOnClose) + CWalletDB(const std::string& strFilename, const char* pszMode = "r+", bool flush_on_close = true) + : CDB(strFilename, pszMode, flush_on_close) { } private: From f636c2cf560264a05ad450ab97dcc0858ba9090a Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 4 Feb 2024 23:26:52 -0500 Subject: [PATCH 31/44] Fix a few more minor Clang warnings --- src/alert.cpp | 4 ++-- src/alert.h | 2 +- src/miner.cpp | 2 -- src/net.cpp | 2 -- src/qt/addressbookpage.h | 2 +- src/qt/guiutil.cpp | 2 +- src/qt/voting/pollwizarddetailspage.cpp | 7 +------ 7 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/alert.cpp b/src/alert.cpp index 0ee441818a..b66293d36b 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -113,11 +113,11 @@ bool CAlert::Cancels(const CAlert& alert) const return (alert.nID <= nCancel || setCancel.count(alert.nID)); } -bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const +bool CAlert::AppliesTo(int version, std::string strSubVerIn) const { // TODO: rework for client-version-embedded-in-strSubVer ? return (IsInEffect() && - nMinVer <= nVersion && nVersion <= nMaxVer && + nMinVer <= version && version <= nMaxVer && (setSubVer.empty() || setSubVer.count(strSubVerIn))); } diff --git a/src/alert.h b/src/alert.h index 50636eca8a..c085de4081 100644 --- a/src/alert.h +++ b/src/alert.h @@ -94,7 +94,7 @@ class CAlert : public CUnsignedAlert uint256 GetHash() const; bool IsInEffect() const; bool Cancels(const CAlert& alert) const; - bool AppliesTo(int nVersion, std::string strSubVerIn) const; + bool AppliesTo(int version, std::string strSubVerIn) const; bool AppliesToMe() const; bool RelayTo(CNode* pnode) const; bool CheckSignature() const; diff --git a/src/miner.cpp b/src/miner.cpp index c95c3ffe02..184d586b2f 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -479,7 +479,6 @@ bool CreateRestOfTheBlock(CBlock &block, CBlockIndex* pindexPrev, - 2) * coinstake_output_ser_size; } - uint64_t nBlockTx = 0; int nBlockSigOps = 100; std::make_heap(vecPriority.begin(), vecPriority.end()); @@ -626,7 +625,6 @@ bool CreateRestOfTheBlock(CBlock &block, CBlockIndex* pindexPrev, block.vtx.push_back(tx); nBlockSize += nTxSize; - ++nBlockTx; nBlockSigOps += nTxSigOps; nFees += nTxFees; diff --git a/src/net.cpp b/src/net.cpp index e6e26e5d90..0f1f87cf0d 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1560,14 +1560,12 @@ void ThreadOpenConnections2(void* parg) // Only connect out to one peer per network group (/16 for IPv4). // Do this here so we don't have to critsect vNodes inside mapAddresses critsect. - int nOutbound = 0; set > setConnected; { LOCK(cs_vNodes); for (auto const& pnode : vNodes) { if (!pnode->fInbound) { setConnected.insert(pnode->addr.GetGroup()); - nOutbound++; } } } diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index d9c91c51c3..fcc2edc1b7 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -42,7 +42,7 @@ class AddressBookPage : public QDialog const QString &getReturnValue() const { return returnValue; } public slots: - void done(int retval); + void done(int retval) override; void exportClicked(); void changeFilter(const QString& needle); void resizeTableColumns(const bool& neighbor_pair_adjust = false, const int& index = 0, diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 7082b578a5..f43dc85779 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -48,7 +48,7 @@ QString dateTimeStr(qint64 nTime) QString formatPingTime(double dPingTime) { - return (dPingTime == std::numeric_limits::max()/1e6 || dPingTime == 0) ? + return (dPingTime >= static_cast(std::numeric_limits::max()) / 1e6 || dPingTime <= 0) ? QObject::tr("N/A") : QObject::tr("%1 ms").arg(QString::number((int)(dPingTime * 1000), 10)); } diff --git a/src/qt/voting/pollwizarddetailspage.cpp b/src/qt/voting/pollwizarddetailspage.cpp index 140e66835e..c282ffecaa 100644 --- a/src/qt/voting/pollwizarddetailspage.cpp +++ b/src/qt/voting/pollwizarddetailspage.cpp @@ -261,12 +261,7 @@ void PollWizardDetailsPage::initializePage() // Only populate poll additional field entries if version >= 3. bool v3_enabled = false; - - { - AssertLockHeld(cs_main); - - v3_enabled = IsPollV3Enabled(nBestHeight); - } + v3_enabled = IsPollV3Enabled(nBestHeight); if (v3_enabled) { poll_item.m_additional_field_entries.push_back( From 81c8154e8729832e7088e2d0dee5fceb2d2539d7 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Mon, 5 Feb 2024 02:26:04 -0500 Subject: [PATCH 32/44] Change some tests to use Fraction class in wallet tests GCC13 and 32 bit x86 seem to have some slightly different results with floating point that appear to be compiler related. This changes the relevant tests to use the Fraction class/Allocation class to use rational arithmetic instead. --- src/test/wallet_tests.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp index 9135984c56..0b674952d2 100755 --- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -1,5 +1,6 @@ #include +#include "gridcoin/sidestake.h" #include "main.h" #include "wallet/wallet.h" @@ -236,18 +237,23 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // test avoiding sub-cent change empty_wallet(); - add_coin(0.0005 * COIN); - add_coin(0.01 * COIN); + // Use rational arithmetic because the floating point has problems with GCC13 on 32 bit architecture x86. + add_coin(static_cast(Fraction(5, 10000, true) * COIN).ToCAmount()); + add_coin(static_cast(Fraction(1, 100, true) * COIN).ToCAmount()); add_coin(1 * COIN); // trying to make 1.0001 from these three coins - BOOST_CHECK( wallet.SelectCoinsMinConf(1.0001 * COIN, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); - BOOST_CHECK_EQUAL(nValueRet, 1.0105 * COIN); // we should get all coins + BOOST_CHECK( wallet.SelectCoinsMinConf(static_cast(Fraction(10001, 10000, true) * COIN).ToCAmount(), + spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + // we should get all coins + BOOST_CHECK(nValueRet == static_cast(Fraction(10105, 10000, true) * COIN).ToCAmount()); BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 3); // but if we try to make 0.999, we should take the bigger of the two small coins to avoid sub-cent change - BOOST_CHECK( wallet.SelectCoinsMinConf(0.999 * COIN, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); - BOOST_CHECK_EQUAL(nValueRet, 1.01 * COIN); // we should get 1 + 0.01 + BOOST_CHECK( wallet.SelectCoinsMinConf(static_cast(Fraction(999, 1000, true) * COIN).ToCAmount(), + spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + // we should get 1 + 0.01 + BOOST_CHECK(nValueRet == static_cast(Fraction(101, 100, true) * COIN).ToCAmount()); BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 2); // test randomness From 7eedaefa9c93bcb814472f5b88594b85f81b9c41 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 18 Feb 2024 12:23:25 -0500 Subject: [PATCH 33/44] Add operator methods to Allocation class This eliminates the requirement to constantly static_cast back to the Allocation class after doing arithmetic operations with Allocations. --- src/gridcoin/sidestake.cpp | 148 ++++++++++++++++++++++++++ src/gridcoin/sidestake.h | 46 ++++++++ src/miner.cpp | 6 +- src/test/gridcoin/sidestake_tests.cpp | 2 +- src/validation.cpp | 4 +- 5 files changed, 200 insertions(+), 6 deletions(-) diff --git a/src/gridcoin/sidestake.cpp b/src/gridcoin/sidestake.cpp index adc324b548..f96bd840db 100644 --- a/src/gridcoin/sidestake.cpp +++ b/src/gridcoin/sidestake.cpp @@ -48,6 +48,14 @@ Allocation::Allocation(const Fraction& f) : Fraction(f) {} +Allocation::Allocation(const int64_t& numerator, const int64_t& denominator) + : Fraction(numerator, denominator) +{} + +Allocation::Allocation(const int64_t& numerator, const int64_t& denominator, const bool& simplify) + : Fraction(numerator, denominator, simplify) +{} + CAmount Allocation::ToCAmount() const { return GetNumerator() / GetDenominator(); @@ -58,6 +66,146 @@ double Allocation::ToPercent() const return ToDouble() * 100.0; } +Allocation Allocation::operator+(const Allocation& rhs) const +{ + return static_cast(Fraction::operator+(rhs)); +} + +Allocation Allocation::operator+(const int64_t& rhs) const +{ + return static_cast(Fraction::operator+(rhs)); +} + +Allocation Allocation::operator-(const Allocation& rhs) const +{ + return static_cast(Fraction::operator-(rhs)); +} + +Allocation Allocation::operator-(const int64_t& rhs) const +{ + return static_cast(Fraction::operator-(rhs)); +} + +Allocation Allocation::operator*(const Allocation& rhs) const +{ + return static_cast(Fraction::operator*(rhs)); +} + +Allocation Allocation::operator*(const int64_t& rhs) const +{ + return static_cast(Fraction::operator*(rhs)); +} + +Allocation Allocation::operator/(const Allocation& rhs) const +{ + return static_cast(Fraction::operator/(rhs)); +} + +Allocation Allocation::operator/(const int64_t& rhs) const +{ + return static_cast(Fraction::operator/(rhs)); +} + +Allocation Allocation::operator+=(const Allocation& rhs) +{ + return static_cast(Fraction::operator+=(rhs)); +} + +Allocation Allocation::operator+=(const int64_t& rhs) +{ + return static_cast(Fraction::operator+=(rhs)); +} + +Allocation Allocation::operator-=(const Allocation& rhs) +{ + return static_cast(Fraction::operator-=(rhs)); +} + +Allocation Allocation::operator-=(const int64_t& rhs) +{ + return static_cast(Fraction::operator-=(rhs)); +} + +Allocation Allocation::operator*=(const Allocation& rhs) +{ + return static_cast(Fraction::operator*=(rhs)); +} + +Allocation Allocation::operator*=(const int64_t& rhs) +{ + return static_cast(Fraction::operator*=(rhs)); +} + +Allocation Allocation::operator/=(const Allocation& rhs) +{ + return static_cast(Fraction::operator/=(rhs)); +} + +Allocation Allocation::operator/=(const int64_t& rhs) +{ + return static_cast(Fraction::operator/=(rhs)); +} + +bool Allocation::operator==(const Allocation& rhs) const +{ + return Fraction::operator==(rhs); +} + +bool Allocation::operator!=(const Allocation& rhs) const +{ + return Fraction::operator!=(rhs); +} + +bool Allocation::operator<=(const Allocation& rhs) const +{ + return Fraction::operator<=(rhs); +} + +bool Allocation::operator>=(const Allocation& rhs) const +{ + return Fraction::operator>=(rhs); +} + +bool Allocation::operator<(const Allocation& rhs) const +{ + return Fraction::operator<(rhs); +} + +bool Allocation::operator>(const Allocation& rhs) const +{ + return Fraction::operator>(rhs); +} + +bool Allocation::operator==(const int64_t& rhs) const +{ + return Fraction::operator==(rhs); +} + +bool Allocation::operator!=(const int64_t& rhs) const +{ + return Fraction::operator!=(rhs); +} + +bool Allocation::operator<=(const int64_t& rhs) const +{ + return Fraction::operator<=(rhs); +} + +bool Allocation::operator>=(const int64_t& rhs) const +{ + return Fraction::operator>=(rhs); +} + +bool Allocation::operator<(const int64_t& rhs) const +{ + return Fraction::operator<(rhs); +} + +bool Allocation::operator>(const int64_t& rhs) const +{ + return Fraction::operator>(rhs); +} + // ----------------------------------------------------------------------------- // Class: LocalSideStake // ----------------------------------------------------------------------------- diff --git a/src/gridcoin/sidestake.h b/src/gridcoin/sidestake.h index 6b001e412d..42613e938c 100644 --- a/src/gridcoin/sidestake.h +++ b/src/gridcoin/sidestake.h @@ -43,6 +43,23 @@ class Allocation : public Fraction //! Allocation(const Fraction& f); + //! + //! \brief Initialize an allocation directly from specifying a numerator and denominator + //! \param numerator + //! \param denominator + //! + Allocation(const int64_t& numerator, const int64_t& denominator); + + //! + //! \brief Initialize an allocation directly from specifying a numerator and denominator, specifying the simplification + //! directive. + //! + //! \param numerator + //! \param denominator + //! \param simplify + //! + Allocation(const int64_t& numerator, const int64_t& denominator, const bool& simplify); + //! //! \brief Allocations extend the Fraction class and can also represent the result of the allocation constructed fraction //! and the result of the multiplication of that fraction times the reward, which is in CAmount (i.e. int64_t). @@ -57,6 +74,35 @@ class Allocation : public Fraction //! \return double percent representation of the allocation fraction. //! double ToPercent() const; + + Allocation operator+(const Allocation& rhs) const; + Allocation operator+(const int64_t& rhs) const; + Allocation operator-(const Allocation& rhs) const; + Allocation operator-(const int64_t& rhs) const; + Allocation operator*(const Allocation& rhs) const; + Allocation operator*(const int64_t& rhs) const; + Allocation operator/(const Allocation& rhs) const; + Allocation operator/(const int64_t& rhs) const; + Allocation operator+=(const Allocation& rhs); + Allocation operator+=(const int64_t& rhs); + Allocation operator-=(const Allocation& rhs); + Allocation operator-=(const int64_t& rhs); + Allocation operator*=(const Allocation& rhs); + Allocation operator*=(const int64_t& rhs); + Allocation operator/=(const Allocation& rhs); + Allocation operator/=(const int64_t& rhs); + bool operator==(const Allocation& rhs) const; + bool operator!=(const Allocation& rhs) const; + bool operator<=(const Allocation& rhs) const; + bool operator>=(const Allocation& rhs) const; + bool operator<(const Allocation& rhs) const; + bool operator>(const Allocation& rhs) const; + bool operator==(const int64_t& rhs) const; + bool operator!=(const int64_t& rhs) const; + bool operator<=(const int64_t& rhs) const; + bool operator>=(const int64_t& rhs) const; + bool operator<(const int64_t& rhs) const; + bool operator>(const int64_t& rhs) const; }; //! diff --git a/src/miner.cpp b/src/miner.cpp index 184d586b2f..bc0ef2deb7 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -968,7 +968,7 @@ void SplitCoinStakeOutput(CBlock &blocknew, int64_t &nReward, bool &fEnableStake if (allocation * nReward < CENT) { LogPrintf("WARN: SplitCoinStakeOutput: distribution %f too small to address %s.", - CoinToDouble(static_cast(allocation * nReward).ToCAmount()), + CoinToDouble((allocation * nReward).ToCAmount()), address.ToString() ); continue; @@ -998,7 +998,7 @@ void SplitCoinStakeOutput(CBlock &blocknew, int64_t &nReward, bool &fEnableStake // For allocations ending less than 100% assign using sidestake allocation. if (SumAllocation + allocation < 1) - nSideStake = static_cast(allocation * nReward).ToCAmount(); + nSideStake = (allocation * nReward).ToCAmount(); // We need to handle the final sidestake differently in the case it brings the total allocation up to 100%, // because testing showed in corner cases the output return to the staking address could be off by one Halford. else if (SumAllocation + allocation == 1) @@ -1010,7 +1010,7 @@ void SplitCoinStakeOutput(CBlock &blocknew, int64_t &nReward, bool &fEnableStake LogPrintf("SplitCoinStakeOutput: create sidestake UTXO %i value %f to address %s", nOutputsUsed, - CoinToDouble(static_cast(allocation * nReward).ToCAmount()), + CoinToDouble((allocation * nReward).ToCAmount()), address.ToString() ); SumAllocation += allocation; diff --git a/src/test/gridcoin/sidestake_tests.cpp b/src/test/gridcoin/sidestake_tests.cpp index 590d2a43f9..c0caa711f5 100644 --- a/src/test/gridcoin/sidestake_tests.cpp +++ b/src/test/gridcoin/sidestake_tests.cpp @@ -140,7 +140,7 @@ BOOST_AUTO_TEST_CASE(sidestake_Allocation_multiplication_and_derivation_of_alloc CAmount max_accrual = 16384 * COIN; - CAmount actual_output = static_cast(allocation * max_accrual).ToCAmount(); + CAmount actual_output = (allocation * max_accrual).ToCAmount(); BOOST_CHECK_EQUAL(actual_output, int64_t {1638236160000}); } diff --git a/src/validation.cpp b/src/validation.cpp index 53268c936a..f60a215ec1 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -891,8 +891,8 @@ class ClaimValidator if (!mandatory_sidestake.empty()) { CAmount actual_output = coinstake.vout[i].nValue; - CAmount required_output = static_cast(mandatory_sidestake[0]->GetAllocation() - * total_owed_to_staker).ToCAmount(); + CAmount required_output = (mandatory_sidestake[0]->GetAllocation() + * total_owed_to_staker).ToCAmount(); if (actual_output >= required_output) { From 4c14a714156beec13c8f937d233fbc62955099aa Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 18 Feb 2024 12:40:17 -0500 Subject: [PATCH 34/44] Cleanup wallet_tests.cpp and remove the rest of double usage This changes out the rest of the double usage to use the Allocation class in a second attempt to fix the i386 linux compile test errors on GCC 13 with OpenSUSE. --- src/test/wallet_tests.cpp | 144 +++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp index 0b674952d2..c5e390e531 100755 --- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -67,29 +67,29 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) empty_wallet(); // with an empty wallet we can't even pay one cent - BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, spendTime, 1, 6, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(!wallet.SelectCoinsMinConf(CENT, spendTime, 1, 6, vCoins, setCoinsRet, nValueRet)); - add_coin(1*CENT, 4); // add a new 1 cent coin + add_coin(CENT, 4); // add a new 1 cent coin // with a new 1 cent coin, we still can't find a mature 1 cent - BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, spendTime, 1, 6, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(!wallet.SelectCoinsMinConf(CENT, spendTime, 1, 6, vCoins, setCoinsRet, nValueRet)); // but we can find a new 1 cent - BOOST_CHECK( wallet.SelectCoinsMinConf( 1 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); - BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); + BOOST_CHECK(wallet.SelectCoinsMinConf(CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, CENT); - add_coin(2*CENT); // add a mature 2 cent coin + add_coin(2 * CENT); // add a mature 2 cent coin // we can't make 3 cents of mature coins - BOOST_CHECK(!wallet.SelectCoinsMinConf( 3 * CENT, spendTime, 1, 6, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(!wallet.SelectCoinsMinConf(3 * CENT, spendTime, 1, 6, vCoins, setCoinsRet, nValueRet)); // we can make 3 cents of new coins - BOOST_CHECK( wallet.SelectCoinsMinConf( 3 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(3 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 3 * CENT); - add_coin(5*CENT); // add a mature 5 cent coin, - add_coin(10*CENT, 3, true); // a new 10 cent coin sent from one of our own addresses - add_coin(20*CENT); // and a mature 20 cent coin + add_coin(5 * CENT); // add a mature 5 cent coin, + add_coin(10 * CENT, 3, true); // a new 10 cent coin sent from one of our own addresses + add_coin(20 * CENT); // and a mature 20 cent coin // now we have new: 1+10=11 (of which 10 was self-sent), and mature: 2+5+20=27. total = 38 @@ -98,109 +98,109 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // we can't even make 37 cents if we don't allow new coins even if they're from us BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, spendTime, 6, 6, vCoins, setCoinsRet, nValueRet)); // but we can make 37 cents if we accept new coins from ourself - BOOST_CHECK( wallet.SelectCoinsMinConf(37 * CENT, spendTime, 1, 6, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(37 * CENT, spendTime, 1, 6, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 37 * CENT); // and we can make 38 cents if we accept all new coins - BOOST_CHECK( wallet.SelectCoinsMinConf(38 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(38 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 38 * CENT); // try making 34 cents from 1,2,5,10,20 - we can't do it exactly - BOOST_CHECK( wallet.SelectCoinsMinConf(34 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); - BOOST_CHECK_GT(nValueRet, 34 * CENT); // but should get more than 34 cents - BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 3); // the best should be 20+10+5. it's incredibly unlikely the 1 or 2 got included (but possible) + BOOST_CHECK(wallet.SelectCoinsMinConf(34 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_GT(nValueRet, 34 * CENT); // but should get more than 34 cents + // the best should be 20+10+5. it's incredibly unlikely the 1 or 2 got included (but possible) + BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 3); // when we try making 7 cents, the smaller coins (1,2,5) are enough. We should see just 2+5 - BOOST_CHECK( wallet.SelectCoinsMinConf( 7 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(7 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 7 * CENT); BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 2); // when we try making 8 cents, the smaller coins (1,2,5) are exactly enough. - BOOST_CHECK( wallet.SelectCoinsMinConf( 8 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(8 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK(nValueRet == 8 * CENT); BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 3); // when we try making 9 cents, no subset of smaller coins is enough, and we get the next bigger coin (10) - BOOST_CHECK( wallet.SelectCoinsMinConf( 9 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(9 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 10 * CENT); BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 1); // now clear out the wallet and start again to test choosing between subsets of smaller coins and the next biggest coin empty_wallet(); - add_coin( 6*CENT); - add_coin( 7*CENT); - add_coin( 8*CENT); - add_coin(20*CENT); - add_coin(30*CENT); // now we have 6+7+8+20+30 = 71 cents total + add_coin(6 * CENT); + add_coin(7 * CENT); + add_coin(8 * CENT); + add_coin(20 * CENT); + add_coin(30 * CENT); // now we have 6+7+8+20+30 = 71 cents total // check that we have 71 and not 72 - BOOST_CHECK( wallet.SelectCoinsMinConf(71 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(71 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK(!wallet.SelectCoinsMinConf(72 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); // now try making 16 cents. the best smaller coins can do is 6+7+8 = 21; not as good at the next biggest coin, 20 - BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(16 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 20 * CENT); // we should get 20 in one coin BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 1); - add_coin( 5*CENT); // now we have 5+6+7+8+20+30 = 75 cents total + add_coin(5 * CENT); // now we have 5+6+7+8+20+30 = 75 cents total // now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, better than the next biggest coin, 20 - BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(16 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 3 coins BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 3); - add_coin( 18*CENT); // now we have 5+6+7+8+18+20+30 + add_coin(18 * CENT); // now we have 5+6+7+8+18+20+30 // and now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, the same as the next biggest coin, 18 - BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(16 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 1 coin BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 1); // because in the event of a tie, the biggest coin wins // now try making 11 cents. we should get 5+6 - BOOST_CHECK( wallet.SelectCoinsMinConf(11 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(11 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 11 * CENT); BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 2); // check that the smallest bigger coin is used - add_coin( 1*COIN); - add_coin( 2*COIN); - add_coin( 3*COIN); - add_coin( 4*COIN); // now we have 5+6+7+8+18+20+30+100+200+300+400 = 1094 cents - BOOST_CHECK( wallet.SelectCoinsMinConf(95 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + add_coin(1 * COIN); + add_coin(2 * COIN); + add_coin(3 * COIN); + add_coin(4 * COIN); // now we have 5+6+7+8+18+20+30+100+200+300+400 = 1094 cents + BOOST_CHECK(wallet.SelectCoinsMinConf(95 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 1 * COIN); // we should get 1 BTC in 1 coin BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 1); - BOOST_CHECK( wallet.SelectCoinsMinConf(195 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(195 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 2 * COIN); // we should get 2 BTC in 1 coin BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 1); // empty the wallet and start again, now with fractions of a cent, to test sub-cent change avoidance empty_wallet(); - add_coin(0.1*CENT); - add_coin(0.2*CENT); - add_coin(0.3*CENT); - add_coin(0.4*CENT); - add_coin(0.5*CENT); + add_coin((GRC::Allocation(1, 10, true) * CENT).ToCAmount()); + add_coin((GRC::Allocation(2, 10, true) * CENT).ToCAmount()); + add_coin((GRC::Allocation(3, 10, true) * CENT).ToCAmount()); + add_coin((GRC::Allocation(4, 10, true) * CENT).ToCAmount()); + add_coin((GRC::Allocation(5, 10, true) * CENT).ToCAmount()); // try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 = 1.5 cents // we'll get sub-cent change whatever happens, so can expect 1.0 exactly - BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); - BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); + BOOST_CHECK(wallet.SelectCoinsMinConf(CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, CENT); // but if we add a bigger coin, making it possible to avoid sub-cent change, things change: - add_coin(1111*CENT); + add_coin(1111 * CENT); // try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 + 1111 = 1112.5 cents - BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); - BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount - + BOOST_CHECK(wallet.SelectCoinsMinConf(CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, CENT); // we should get the exact amount // if we add more sub-cent coins: - add_coin(0.6*CENT); - add_coin(0.7*CENT); + add_coin((GRC::Allocation(6, 10, true) * CENT).ToCAmount()); + add_coin((GRC::Allocation(7, 10, true) * CENT).ToCAmount()); // and try again to make 1.0 cents, we can still make 1.0 cents - BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); - BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount + BOOST_CHECK(wallet.SelectCoinsMinConf(CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, CENT); // we should get the exact amount // run the 'mtgox' test (see http://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf) // they tried to consolidate 10 50k coins into one 500k coin, and ended up with 50k in change @@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) for (int i = 0; i < 20; i++) add_coin(50000 * COIN); - BOOST_CHECK( wallet.SelectCoinsMinConf(500000 * COIN, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(500000 * COIN, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 500000 * COIN); // we should get the exact amount BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 10); // in ten coins @@ -217,43 +217,43 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // sometimes it will fail, and so we use the next biggest coin: empty_wallet(); - add_coin(0.5 * CENT); - add_coin(0.6 * CENT); - add_coin(0.7 * CENT); + add_coin((GRC::Allocation(5, 10, true) * CENT).ToCAmount()); + add_coin((GRC::Allocation(6, 10, true) * CENT).ToCAmount()); + add_coin((GRC::Allocation(7, 10, true) * CENT).ToCAmount()); add_coin(1111 * CENT); - BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 1111 * CENT); // we get the bigger coin BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 1); // but sometimes it's possible, and we use an exact subset (0.4 + 0.6 = 1.0) empty_wallet(); - add_coin(0.4 * CENT); - add_coin(0.6 * CENT); - add_coin(0.8 * CENT); + add_coin((GRC::Allocation(4, 10, true) * CENT).ToCAmount()); + add_coin((GRC::Allocation(6, 10, true) * CENT).ToCAmount()); + add_coin((GRC::Allocation(8, 10, true) * CENT).ToCAmount()); add_coin(1111 * CENT); - BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); - BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount + BOOST_CHECK(wallet.SelectCoinsMinConf(CENT, spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, CENT); // we should get the exact amount BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 2); // in two coins 0.4+0.6 // test avoiding sub-cent change empty_wallet(); // Use rational arithmetic because the floating point has problems with GCC13 on 32 bit architecture x86. - add_coin(static_cast(Fraction(5, 10000, true) * COIN).ToCAmount()); - add_coin(static_cast(Fraction(1, 100, true) * COIN).ToCAmount()); - add_coin(1 * COIN); + add_coin((GRC::Allocation(5, 10000, true) * COIN).ToCAmount()); + add_coin((GRC::Allocation(1, 100, true) * COIN).ToCAmount()); + add_coin(COIN); // trying to make 1.0001 from these three coins - BOOST_CHECK( wallet.SelectCoinsMinConf(static_cast(Fraction(10001, 10000, true) * COIN).ToCAmount(), + BOOST_CHECK(wallet.SelectCoinsMinConf((GRC::Allocation(10001, 10000, true) * COIN).ToCAmount(), spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); // we should get all coins - BOOST_CHECK(nValueRet == static_cast(Fraction(10105, 10000, true) * COIN).ToCAmount()); + BOOST_CHECK(nValueRet == (GRC::Allocation(10105, 10000, true) * COIN).ToCAmount()); BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 3); // but if we try to make 0.999, we should take the bigger of the two small coins to avoid sub-cent change - BOOST_CHECK( wallet.SelectCoinsMinConf(static_cast(Fraction(999, 1000, true) * COIN).ToCAmount(), + BOOST_CHECK(wallet.SelectCoinsMinConf((GRC::Allocation(999, 1000, true) * COIN).ToCAmount(), spendTime, 1, 1, vCoins, setCoinsRet, nValueRet)); // we should get 1 + 0.01 - BOOST_CHECK(nValueRet == static_cast(Fraction(101, 100, true) * COIN).ToCAmount()); + BOOST_CHECK(nValueRet == (GRC::Allocation(101, 100, true) * COIN).ToCAmount()); BOOST_CHECK_EQUAL(setCoinsRet.size(), (size_t) 2); // test randomness @@ -283,15 +283,15 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // add 75 cents in small change. not enough to make 90 cents, // then try making 90 cents. there are multiple competing "smallest bigger" coins, // one of which should be picked at random - add_coin( 5*CENT); add_coin(10*CENT); add_coin(15*CENT); add_coin(20*CENT); add_coin(25*CENT); + add_coin(5 * CENT); add_coin(10 * CENT); add_coin(15 * CENT); add_coin(20 * CENT); add_coin(25 * CENT); fails = 0; for (int i = 0; i < RANDOM_REPEATS; i++) { // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time // run the test RANDOM_REPEATS times and only complain if all of them fail - BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, spendTime, 1, 6, vCoins, setCoinsRet , nValueRet)); - BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, spendTime, 1, 6, vCoins, setCoinsRet2, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(90 * CENT, spendTime, 1, 6, vCoins, setCoinsRet , nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(90 * CENT, spendTime, 1, 6, vCoins, setCoinsRet2, nValueRet)); if (equal_sets(setCoinsRet, setCoinsRet2)) fails++; } From a674f0f86b0dba006a5f912c3d216ed224095cba Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sat, 10 Feb 2024 20:00:59 -0500 Subject: [PATCH 35/44] Implement custom upgrade notification dialog box Also allow updatedialog to be called from About Gridcoin --- src/Makefile.qt.include | 4 ++ src/gridcoin/upgrade.cpp | 115 ++++++++++++++++++++++------------- src/gridcoin/upgrade.h | 10 ++- src/node/ui_interface.cpp | 2 +- src/node/ui_interface.h | 2 +- src/noui.cpp | 2 +- src/qt/CMakeLists.txt | 1 + src/qt/aboutdialog.cpp | 33 ++++++++++ src/qt/aboutdialog.h | 1 + src/qt/bitcoin.cpp | 6 +- src/qt/bitcoingui.cpp | 19 +++--- src/qt/bitcoingui.h | 5 +- src/qt/forms/aboutdialog.ui | 37 +++++++++++ src/qt/forms/updatedialog.ui | 98 +++++++++++++++++++++++++++++ src/qt/updatedialog.cpp | 55 +++++++++++++++++ src/qt/updatedialog.h | 32 ++++++++++ src/qt/upgradeqt.cpp | 4 +- src/wallet/diagnose.h | 6 +- 18 files changed, 368 insertions(+), 64 deletions(-) create mode 100644 src/qt/forms/updatedialog.ui create mode 100644 src/qt/updatedialog.cpp create mode 100644 src/qt/updatedialog.h diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 6e67219bec..ffc7dad3cb 100755 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -106,6 +106,7 @@ QT_FORMS_UI = \ qt/forms/sendcoinsentry.ui \ qt/forms/signverifymessagedialog.ui \ qt/forms/transactiondescdialog.ui \ + qt/forms/updatedialog.ui \ qt/forms/voting/additionalfieldstableview.ui \ qt/forms/voting/pollcard.ui \ qt/forms/voting/pollcardview.ui \ @@ -171,6 +172,7 @@ QT_MOC_CPP = \ qt/moc_transactionfilterproxy.cpp \ qt/moc_transactiontablemodel.cpp \ qt/moc_transactionview.cpp \ + qt/moc_updatedialog.cpp \ qt/moc_walletmodel.cpp \ qt/researcher/moc_projecttablemodel.cpp \ qt/researcher/moc_researchermodel.cpp \ @@ -298,6 +300,7 @@ GRIDCOINRESEARCH_QT_H = \ qt/transactionrecord.h \ qt/transactiontablemodel.h \ qt/transactionview.h \ + qt/updatedialog.h \ qt/upgradeqt.h \ qt/voting/additionalfieldstableview.h \ qt/voting/additionalfieldstablemodel.h \ @@ -388,6 +391,7 @@ GRIDCOINRESEARCH_QT_CPP = \ qt/transactiontablemodel.cpp \ qt/transactionview.cpp \ qt/upgradeqt.cpp \ + qt/updatedialog.cpp \ qt/voting/additionalfieldstableview.cpp \ qt/voting/additionalfieldstablemodel.cpp \ qt/voting/poll_types.cpp \ diff --git a/src/gridcoin/upgrade.cpp b/src/gridcoin/upgrade.cpp index aa45fe12bd..f52d08e1bf 100644 --- a/src/gridcoin/upgrade.cpp +++ b/src/gridcoin/upgrade.cpp @@ -32,12 +32,16 @@ Upgrade::Upgrade() void Upgrade::ScheduledUpdateCheck() { - std::string VersionResponse = ""; + std::string VersionResponse; + std::string change_log; + + Upgrade::UpgradeType upgrade_type {Upgrade::UpgradeType::Unknown}; - CheckForLatestUpdate(VersionResponse); + CheckForLatestUpdate(VersionResponse, change_log, upgrade_type); } -bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dialog, bool snapshotrequest) +bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, std::string& change_log, Upgrade::UpgradeType& upgrade_type, + bool ui_dialog, bool snapshotrequest) { // If testnet skip this || If the user changes this to disable while wallet running just drop out of here now. // (Need a way to remove items from scheduler.) @@ -46,8 +50,8 @@ bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dial Http VersionPull; - std::string GithubResponse = ""; - std::string VersionResponse = ""; + std::string GithubResponse; + std::string VersionResponse; // We receive the response and it's in a json reply UniValue Response(UniValue::VOBJ); @@ -64,15 +68,15 @@ bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dial if (VersionResponse.empty()) { - LogPrintf("WARNING %s: No Response from GitHub", __func__); + LogPrintf("WARNING: %s: No Response from GitHub", __func__); return false; } - std::string GithubReleaseData = ""; - std::string GithubReleaseTypeData = ""; - std::string GithubReleaseBody = ""; - std::string GithubReleaseType = ""; + std::string GithubReleaseData; + std::string GithubReleaseTypeData; + std::string GithubReleaseBody; + std::string GithubReleaseType; try { @@ -95,14 +99,19 @@ bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dial } GithubReleaseTypeData = ToLower(GithubReleaseTypeData); - if (GithubReleaseTypeData.find("leisure") != std::string::npos) - GithubReleaseType = _("leisure"); - else if (GithubReleaseTypeData.find("mandatory") != std::string::npos) + if (GithubReleaseTypeData.find("leisure") != std::string::npos) { + GithubReleaseType = _("leisure"); + upgrade_type = Upgrade::UpgradeType::Leisure; + } else if (GithubReleaseTypeData.find("mandatory") != std::string::npos) { GithubReleaseType = _("mandatory"); - - else + // This will be confirmed below by also checking the second position version. If not incremented, then it will + // be set to unknown. + upgrade_type = Upgrade::UpgradeType::Mandatory; + } else { GithubReleaseType = _("unknown"); + upgrade_type = Upgrade::UpgradeType::Unknown; + } // Parse version data std::vector GithubVersion; @@ -113,6 +122,7 @@ bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dial LocalVersion.push_back(CLIENT_VERSION_MAJOR); LocalVersion.push_back(CLIENT_VERSION_MINOR); LocalVersion.push_back(CLIENT_VERSION_REVISION); + LocalVersion.push_back(CLIENT_VERSION_BUILD); if (GithubVersion.size() != 4) { @@ -123,60 +133,79 @@ bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dial bool NewVersion = false; bool NewMandatory = false; + bool same_version = true; try { // Left to right version numbers. - // 3 numbers to check for production. - for (unsigned int x = 0; x < 3; x++) - { + // 4 numbers to check. + for (unsigned int x = 0; x <= 3; x++) { int github_version = 0; - if (!ParseInt32(GithubVersion[x], &github_version)) - { + if (!ParseInt32(GithubVersion[x], &github_version)) { throw std::invalid_argument("Failed to parse GitHub version from official GitHub project repo."); } - if (github_version > LocalVersion[x]) - { + if (github_version > LocalVersion[x]) { NewVersion = true; - if (x < 2) - { + same_version = false; + + if (x < 2 && upgrade_type == Upgrade::UpgradeType::Mandatory) { NewMandatory = true; + } else { + upgrade_type = Upgrade::UpgradeType::Unknown; } - break; + } else { + same_version &= (github_version == LocalVersion[x]); } } - } - catch (std::exception& ex) - { + } catch (std::exception& ex) { error("%s: Exception occurred checking client version against GitHub version (%s)", __func__, ToString(ex.what())); + upgrade_type = Upgrade::UpgradeType::Unknown; return false; } - if (!NewVersion) return NewVersion; - - // New version was found + // Populate client_message_out regardless of whether new version is found, because we are using this method for + // the version information button in the "About Gridcoin" dialog. client_message_out = _("Local version: ") + strprintf("%d.%d.%d.%d", CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD) + "\r\n"; client_message_out.append(_("GitHub version: ") + GithubReleaseData + "\r\n"); - client_message_out.append(_("This update is ") + GithubReleaseType + "\r\n\r\n"); - // For snapshot requests we will handle things differently after this point - if (snapshotrequest && NewMandatory) - return NewVersion; + if (NewVersion) { + client_message_out.append(_("This update is ") + GithubReleaseType + "\r\n\r\n"); + } else if (same_version) { + client_message_out.append(_("The latest release is ") + GithubReleaseType + "\r\n\r\n"); + client_message_out.append(_("You are running the latest release.") + "\n"); + } else { + client_message_out.append(_("The latest release is ") + GithubReleaseType + "\r\n\r\n"); + + // If not a new version available and the version is not the same, the only thing left is that we are running + // a version greater than the latest release version, so set the upgrade_type to Unsupported, which is used for a + // warning. + upgrade_type = Upgrade::UpgradeType::Unsupported; + client_message_out.append(_("WARNING: You are running a version that is higher than the latest release.") + "\n"); + } + + change_log = GithubReleaseBody; + + if (!NewVersion) return false; - if (NewMandatory) + // For snapshot requests we will only return true if there is a new mandatory version AND the snapshotrequest boolean + // is set true. This is because the snapshot request context is looking for the presence of a new mandatory to block + // the snapshot download before upgrading to the new mandatory if there is one. + if (snapshotrequest && NewMandatory) return true; + + if (NewMandatory) { client_message_out.append(_("WARNING: A mandatory release is available. Please upgrade as soon as possible.") + "\n"); + } - std::string ChangeLog = GithubReleaseBody; - - if (ui_dialog) - uiInterface.UpdateMessageBox(client_message_out, ChangeLog); + if (ui_dialog) { + uiInterface.UpdateMessageBox(client_message_out, static_cast(upgrade_type), change_log); + } - return NewVersion; + return true; } void Upgrade::SnapshotMain() @@ -188,8 +217,10 @@ void Upgrade::SnapshotMain() // Verify a mandatory release is not available before we continue to snapshot download. std::string VersionResponse = ""; + std::string change_log; + Upgrade::UpgradeType upgrade_type {Upgrade::UpgradeType::Unknown}; - if (CheckForLatestUpdate(VersionResponse, false, true)) + if (CheckForLatestUpdate(VersionResponse, change_log, upgrade_type, false, true)) { std::cout << this->ResetBlockchainMessages(UpdateAvailable) << std::endl; std::cout << this->ResetBlockchainMessages(GithubResponse) << std::endl; diff --git a/src/gridcoin/upgrade.h b/src/gridcoin/upgrade.h index daa1efba8f..c4dac3fce9 100644 --- a/src/gridcoin/upgrade.h +++ b/src/gridcoin/upgrade.h @@ -125,6 +125,13 @@ class Upgrade GithubResponse }; + enum UpgradeType { + Unknown, + Leisure, + Mandatory, + Unsupported //! This is used for a running version that is greater than the current official release. + }; + //! //! \brief Scheduler call to CheckForLatestUpdate //! @@ -133,7 +140,8 @@ class Upgrade //! //! \brief Check for latest updates on GitHub. //! - static bool CheckForLatestUpdate(std::string& client_message_out, bool ui_dialog = true, bool snapshotrequest = false); + static bool CheckForLatestUpdate(std::string& client_message_out, std::string& change_log, UpgradeType& upgrade_type, + bool ui_dialog = true, bool snapshotrequest = false); //! //! \brief Function that will be threaded to download snapshot diff --git a/src/node/ui_interface.cpp b/src/node/ui_interface.cpp index c412d77269..297d64997a 100644 --- a/src/node/ui_interface.cpp +++ b/src/node/ui_interface.cpp @@ -67,7 +67,7 @@ ADD_SIGNALS_IMPL_WRAPPER(UpdateMessageBox); ADD_SIGNALS_IMPL_WRAPPER(RwSettingsUpdated); void CClientUIInterface::ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style) { return g_ui_signals.ThreadSafeMessageBox(message, caption, style); } -void CClientUIInterface::UpdateMessageBox(const std::string& version, const std::string& message) { return g_ui_signals.UpdateMessageBox(version, message); } +void CClientUIInterface::UpdateMessageBox(const std::string& version, const int& update_type, const std::string& message) { return g_ui_signals.UpdateMessageBox(version, update_type, message); } bool CClientUIInterface::ThreadSafeAskFee(int64_t nFeeRequired, const std::string& strCaption) { return g_ui_signals.ThreadSafeAskFee(nFeeRequired, strCaption).value_or(false); } bool CClientUIInterface::ThreadSafeAskQuestion(std::string caption, std::string body) { return g_ui_signals.ThreadSafeAskQuestion(caption, body).value_or(false); } void CClientUIInterface::ThreadSafeHandleURI(const std::string& strURI) { return g_ui_signals.ThreadSafeHandleURI(strURI); } diff --git a/src/node/ui_interface.h b/src/node/ui_interface.h index a0917c573a..6a2aa852be 100644 --- a/src/node/ui_interface.h +++ b/src/node/ui_interface.h @@ -88,7 +88,7 @@ class CClientUIInterface ADD_SIGNALS_DECL_WRAPPER(ThreadSafeMessageBox, void, const std::string& message, const std::string& caption, int style); /** Update notification message box. */ - ADD_SIGNALS_DECL_WRAPPER(UpdateMessageBox, void, const std::string& version, const std::string& message); + ADD_SIGNALS_DECL_WRAPPER(UpdateMessageBox, void, const std::string& version, const int& update_type, const std::string& message); /** Ask the user whether they want to pay a fee or not. */ ADD_SIGNALS_DECL_WRAPPER(ThreadSafeAskFee, bool, int64_t nFeeRequired, const std::string& strCaption); diff --git a/src/noui.cpp b/src/noui.cpp index 033b04df56..188b7f8bba 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -21,7 +21,7 @@ static bool noui_ThreadSafeAskFee(int64_t nFeeRequired, const std::string& strCa return true; } -static int noui_UpdateMessageBox(const std::string& version, const std::string& message) +static int noui_UpdateMessageBox(const std::string& version, const int& upgrade_type, const std::string& message) { std::string caption = _("Gridcoin Update Available"); diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index b62d55953b..9a763d4e37 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -71,6 +71,7 @@ add_library(gridcoinqt STATIC transactionrecord.cpp transactiontablemodel.cpp transactionview.cpp + updatedialog.cpp upgradeqt.cpp voting/additionalfieldstableview.cpp voting/additionalfieldstablemodel.cpp diff --git a/src/qt/aboutdialog.cpp b/src/qt/aboutdialog.cpp index b8707c941c..53e0e443c3 100755 --- a/src/qt/aboutdialog.cpp +++ b/src/qt/aboutdialog.cpp @@ -2,6 +2,8 @@ #include "qt/decoration.h" #include "ui_aboutdialog.h" #include "clientmodel.h" +#include "updatedialog.h" +#include "util.h" AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), @@ -11,6 +13,12 @@ AboutDialog::AboutDialog(QWidget *parent) : ui->copyrightLabel->setText("Copyright 2009-2024 The Bitcoin/Peercoin/Black-Coin/Gridcoin developers"); resize(GRC::ScaleSize(this, width(), height())); + + if (!fTestNet) { + connect(ui->versionInfoButton, &QAbstractButton::pressed, this, [this]() { handlePressVersionInfoButton(); }); + } else { + ui->versionInfoButton->hide(); + } } void AboutDialog::setModel(ClientModel *model) @@ -30,3 +38,28 @@ void AboutDialog::on_buttonBox_accepted() { close(); } + +void AboutDialog::handlePressVersionInfoButton() +{ + std::string client_message_out; + std::string change_log; + GRC::Upgrade::UpgradeType upgrade_type = GRC::Upgrade::UpgradeType::Unknown; + + + GRC::Upgrade::CheckForLatestUpdate(client_message_out, change_log, upgrade_type, false, false); + + if (client_message_out == std::string {}) { + client_message_out = "No response from GitHub - check network connectivity."; + change_log = " "; + } + + UpdateDialog update_dialog; + + update_dialog.setWindowTitle("Gridcoin Version Information"); + update_dialog.setVersion(QString().fromStdString(client_message_out)); + update_dialog.setUpgradeType(static_cast(upgrade_type)); + update_dialog.setDetails(QString().fromStdString(change_log)); + update_dialog.setModal(false); + + update_dialog.exec(); +} diff --git a/src/qt/aboutdialog.h b/src/qt/aboutdialog.h index 1b1dba84d7..a517b262b0 100644 --- a/src/qt/aboutdialog.h +++ b/src/qt/aboutdialog.h @@ -23,6 +23,7 @@ class AboutDialog : public QDialog private slots: void on_buttonBox_accepted(); + void handlePressVersionInfoButton(); }; #endif // BITCOIN_QT_ABOUTDIALOG_H diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 82bd5a8ab1..24028b6be3 100755 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -192,16 +192,16 @@ static void InitMessage(const std::string &message) } } -static void UpdateMessageBox(const std::string& version, const std::string& message) +static void UpdateMessageBox(const std::string& version, const int& update_version, const std::string& message) { std::string caption = _("Gridcoin Update Available"); if (guiref) { - std::string guiaddition = version + _("Click \"Show Details\" to view changes in latest update."); QMetaObject::invokeMethod(guiref, "update", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(caption)), - Q_ARG(QString, QString::fromStdString(guiaddition)), + Q_ARG(QString, QString::fromStdString(version)), + Q_ARG(int, update_version), Q_ARG(QString, QString::fromStdString(message))); } diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index aa7c86315f..37fa568a96 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -45,6 +45,7 @@ #include "upgradeqt.h" #include "voting/votingmodel.h" #include "voting/polltablemodel.h" +#include "updatedialog.h" #ifdef Q_OS_MAC #include "macdockiconhandler.h" @@ -1159,22 +1160,20 @@ void BitcoinGUI::error(const QString &title, const QString &message, bool modal) } } -void BitcoinGUI::update(const QString &title, const QString& version, const QString &message) +void BitcoinGUI::update(const QString &title, const QString& version, const int& upgrade_type, const QString &message) { - // Create our own message box; A dialog can go here in future for qt if we choose - - updateMessageDialog.reset(new QMessageBox); + updateMessageDialog.reset(new UpdateDialog); updateMessageDialog->setWindowTitle(title); - updateMessageDialog->setText(version); - updateMessageDialog->setDetailedText(message); - updateMessageDialog->setIcon(QMessageBox::Information); - updateMessageDialog->setStandardButtons(QMessageBox::Ok); + updateMessageDialog->setVersion(version); + updateMessageDialog->setUpgradeType(static_cast(upgrade_type)); + updateMessageDialog->setDetails(message); updateMessageDialog->setModal(false); - connect(updateMessageDialog.get(), &QMessageBox::finished, [this](int) { updateMessageDialog.reset(); }); + + connect(updateMessageDialog.get(), &QDialog::finished, this, [this]() { updateMessageDialog.reset(); }); + // Due to slight delay in gui load this could appear behind the gui ui // The only other option available would make the message box stay on top of all applications - QTimer::singleShot(5000, updateMessageDialog.get(), [this]() { updateMessageDialog->show(); }); } diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 5b1413cbbf..e1934f8348 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -32,6 +32,7 @@ class Notificator; class RPCConsole; class DiagnosticsDialog; class ClickLabel; +class UpdateDialog; QT_BEGIN_NAMESPACE class QLabel; @@ -110,7 +111,7 @@ class BitcoinGUI : public QMainWindow TransactionView *transactionView; VotingPage *votingPage; SignVerifyMessageDialog *signVerifyMessageDialog; - std::unique_ptr updateMessageDialog; + std::unique_ptr updateMessageDialog; QLabel *statusbarAlertsLabel; QLabel *labelEncryptionIcon; @@ -205,7 +206,7 @@ public slots: void setEncryptionStatus(int status); /** Notify the user if there is an update available */ - void update(const QString& title, const QString& version, const QString& message); + void update(const QString& title, const QString& version, const int& upgrade_type, const QString& message); /** Notify the user of an error in the network or transaction handling code. */ void error(const QString &title, const QString &message, bool modal); diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui index c67bdbac35..e3952591f1 100644 --- a/src/qt/forms/aboutdialog.ui +++ b/src/qt/forms/aboutdialog.ui @@ -136,6 +136,43 @@ This product includes software developed by the OpenSSL Project for use in the O + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Version Information + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/src/qt/forms/updatedialog.ui b/src/qt/forms/updatedialog.ui new file mode 100644 index 0000000000..d713ec8b28 --- /dev/null +++ b/src/qt/forms/updatedialog.ui @@ -0,0 +1,98 @@ + + + UpdateDialog + + + + 0 + 0 + 609 + 430 + + + + Dialog + + + + + + + + icon + + + + + + + version + + + + + + + + + false + + + true + + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + changelog + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + UpdateDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + UpdateDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qt/updatedialog.cpp b/src/qt/updatedialog.cpp new file mode 100644 index 0000000000..c5e55649d5 --- /dev/null +++ b/src/qt/updatedialog.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2014-2024 The Gridcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include "updatedialog.h" +#include "qicon.h" +#include "qstyle.h" +#include "qt/decoration.h" + +#include "ui_updatedialog.h" + +UpdateDialog::UpdateDialog(QWidget* parent) + : QDialog(parent) + , ui(new Ui::UpdateDialog) +{ + ui->setupUi(this); + + resize(GRC::ScaleSize(this, width(), height())); +} + +UpdateDialog::~UpdateDialog() +{ + delete ui; +} + +void UpdateDialog::setVersion(QString version) +{ + ui->versionData->setText(version); +} + +void UpdateDialog::setDetails(QString message) +{ + ui->versionDetails->setText(message); +} + +void UpdateDialog::setUpgradeType(GRC::Upgrade::UpgradeType upgrade_type) +{ + QIcon info_icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); + QIcon warning_icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); + QIcon unknown_icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxQuestion); + + switch (upgrade_type) { + case GRC::Upgrade::UpgradeType::Mandatory: + [[fallthrough]]; + case GRC::Upgrade::UpgradeType::Unsupported: + ui->infoIcon->setPixmap(GRC::ScaleIcon(this, warning_icon, 48)); + break; + case GRC::Upgrade::UpgradeType::Leisure: + ui->infoIcon->setPixmap(GRC::ScaleIcon(this, info_icon, 48)); + break; + case GRC::Upgrade::Unknown: + ui->infoIcon->setPixmap(GRC::ScaleIcon(this, unknown_icon, 48)); + break; + } +} diff --git a/src/qt/updatedialog.h b/src/qt/updatedialog.h new file mode 100644 index 0000000000..7987b706f7 --- /dev/null +++ b/src/qt/updatedialog.h @@ -0,0 +1,32 @@ +// Copyright (c) 2014-2024 The Gridcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_UPDATEDIALOG_H +#define BITCOIN_QT_UPDATEDIALOG_H + +#include "gridcoin/upgrade.h" +#include + +namespace Ui { +class UpdateDialog; +} + +class UpdateDialog : public QDialog +{ + Q_OBJECT + +public: + explicit UpdateDialog(QWidget* parent = nullptr); + ~UpdateDialog(); + + void setVersion(QString version); + void setDetails(QString message); + void setUpgradeType(GRC::Upgrade::UpgradeType upgrade_type); + +private: + Ui::UpdateDialog *ui; + +}; + +#endif // BITCOIN_QT_UPDATEDIALOG_H diff --git a/src/qt/upgradeqt.cpp b/src/qt/upgradeqt.cpp index 6bbfd9519d..9499d5a032 100644 --- a/src/qt/upgradeqt.cpp +++ b/src/qt/upgradeqt.cpp @@ -41,8 +41,10 @@ bool UpgradeQt::SnapshotMain(QApplication& SnapshotApp) // Verify a mandatory release is not available before we continue to snapshot download. std::string VersionResponse = ""; + std::string change_log; + Upgrade::UpgradeType upgrade_type {Upgrade::UpgradeType::Unknown}; - if (UpgradeMain.CheckForLatestUpdate(VersionResponse, false, true)) + if (UpgradeMain.CheckForLatestUpdate(VersionResponse, change_log, upgrade_type, false, true)) { ErrorMsg(UpgradeMain.ResetBlockchainMessages(Upgrade::UpdateAvailable), UpgradeMain.ResetBlockchainMessages(Upgrade::GithubResponse) + "\r\n" + VersionResponse); diff --git a/src/wallet/diagnose.h b/src/wallet/diagnose.h index f931fc45e1..606b0205ec 100644 --- a/src/wallet/diagnose.h +++ b/src/wallet/diagnose.h @@ -403,14 +403,16 @@ class CheckClientVersion : public Diagnose m_results_tip_arg.clear(); std::string client_message; + std::string change_log; + GRC::Upgrade::UpgradeType upgrade_type {GRC::Upgrade::UpgradeType::Unknown}; - if (g_UpdateChecker->CheckForLatestUpdate(client_message, false) + if (g_UpdateChecker->CheckForLatestUpdate(client_message, change_log, upgrade_type, false) && client_message.find("mandatory") != std::string::npos) { m_results_tip = _("There is a new mandatory version available and you should upgrade as soon as possible to " "ensure your wallet remains in consensus with the network."); m_results = Diagnose::FAIL; - } else if (g_UpdateChecker->CheckForLatestUpdate(client_message, false) + } else if (g_UpdateChecker->CheckForLatestUpdate(client_message, change_log, upgrade_type, false) && client_message.find("mandatory") == std::string::npos) { m_results_tip = _("There is a new leisure version available and you should upgrade as soon as practical."); m_results = Diagnose::WARNING; From 34f3d590a083f36493e3373bcf20d6896e88d20c Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 18 Feb 2024 20:10:20 -0500 Subject: [PATCH 36/44] Change versionInfoButton logic to use disable instead of hide() Co-authored-by: div72 <60045611+div72@users.noreply.github.com> --- src/qt/aboutdialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qt/aboutdialog.cpp b/src/qt/aboutdialog.cpp index 53e0e443c3..554a0eb2f3 100755 --- a/src/qt/aboutdialog.cpp +++ b/src/qt/aboutdialog.cpp @@ -17,7 +17,8 @@ AboutDialog::AboutDialog(QWidget *parent) : if (!fTestNet) { connect(ui->versionInfoButton, &QAbstractButton::pressed, this, [this]() { handlePressVersionInfoButton(); }); } else { - ui->versionInfoButton->hide(); + ui->versionInfoButton->setDisabled(true); + ui->versionInfoButton->setToolTip(tr("Version information is not available on testnet.")); } } From 7587db372f451c1aa95b03fa010db433e05f9f89 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 18 Feb 2024 21:06:08 -0500 Subject: [PATCH 37/44] Add disableupdatecheck argument check in aboutdialog version info button --- src/qt/aboutdialog.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qt/aboutdialog.cpp b/src/qt/aboutdialog.cpp index 554a0eb2f3..35f2df5b44 100755 --- a/src/qt/aboutdialog.cpp +++ b/src/qt/aboutdialog.cpp @@ -14,8 +14,12 @@ AboutDialog::AboutDialog(QWidget *parent) : resize(GRC::ScaleSize(this, width(), height())); - if (!fTestNet) { + if (!fTestNet && !gArgs.GetBoolArg("-disableupdatecheck", false)) { connect(ui->versionInfoButton, &QAbstractButton::pressed, this, [this]() { handlePressVersionInfoButton(); }); + } else if (gArgs.GetBoolArg("-disableupdatecheck", false)) { + ui->versionInfoButton->setDisabled(true); + ui->versionInfoButton->setToolTip(tr("Version information and update check has been disabled " + "by config or startup parameter.")); } else { ui->versionInfoButton->setDisabled(true); ui->versionInfoButton->setToolTip(tr("Version information is not available on testnet.")); From a59051a5679386aabc73821dd81cde525d3faaa5 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 18 Feb 2024 21:20:32 -0500 Subject: [PATCH 38/44] Pull copyright year for About Gridcoin from gridcoin-config.h --- src/qt/aboutdialog.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/qt/aboutdialog.cpp b/src/qt/aboutdialog.cpp index 35f2df5b44..0f18d289d4 100755 --- a/src/qt/aboutdialog.cpp +++ b/src/qt/aboutdialog.cpp @@ -10,7 +10,23 @@ AboutDialog::AboutDialog(QWidget *parent) : ui(new Ui::AboutDialog) { ui->setupUi(this); - ui->copyrightLabel->setText("Copyright 2009-2024 The Bitcoin/Peercoin/Black-Coin/Gridcoin developers"); + + QString copyrightText = "Copyright 2009-"; + std::variant copyright_year = COPYRIGHT_YEAR; + + try { + copyrightText += QString::number(std::get(copyright_year)); + } catch (const std::bad_variant_access& e) { + try { + copyrightText += std::get(copyright_year); + } catch (const std::bad_variant_access& e) { + copyrightText += "Present"; + } + } + + copyrightText += " The Bitcoin/Peercoin/Black-Coin/Gridcoin developers"; + + ui->copyrightLabel->setText(copyrightText); resize(GRC::ScaleSize(this, width(), height())); From 7bfd1b4a094c4211a84b00d3aff76f7bb9c50db2 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Thu, 22 Feb 2024 15:25:23 -0500 Subject: [PATCH 39/44] Implement comp_double comparison function in certain tests This is the final fix for the openSUSE GCC13 i386 floating point issues. This implements a special comp_double comparison function for certain doubles to deal with the small errors introduced in string to floating point conversions on openSUSE GCC13 x86 32-bit. --- src/test/gridcoin/claim_tests.cpp | 34 ++++++++++--- src/test/gridcoin/researcher_tests.cpp | 68 +++++++++++++++++--------- 2 files changed, 71 insertions(+), 31 deletions(-) diff --git a/src/test/gridcoin/claim_tests.cpp b/src/test/gridcoin/claim_tests.cpp index 0a9b5f1af4..33d1e204ad 100644 --- a/src/test/gridcoin/claim_tests.cpp +++ b/src/test/gridcoin/claim_tests.cpp @@ -97,6 +97,26 @@ static CKey GetTestPrivateKey() return key; } + +// Unfortunately, GCC 13 on openSUSE i386 is misbehaving and exhibiting weird errors in the last decimal places for things +// even as straightforward as +// +// double foo = 0.0; +// text >> foo. +// +// This comparison function works around that by allowing a small error band to pass the tests, but not enough to invalidate +// the tests on compilers that work. +bool comp_double(double lhs, double rhs) +{ + // Require exact match if 0=0. + if (std::min(lhs, rhs) == 0.0) { + return (lhs == rhs); + } else { + double unsigned_rel_error = std::abs(lhs - rhs) / std::min(lhs, rhs); + + return (unsigned_rel_error <= double {1e-8}); + } +} } // anonymous namespace // ----------------------------------------------------------------------------- @@ -118,7 +138,7 @@ BOOST_AUTO_TEST_CASE(it_initializes_to_an_empty_claim) BOOST_CHECK(claim.m_magnitude == 0); BOOST_CHECK(claim.m_research_subsidy == 0); - BOOST_CHECK(claim.m_magnitude_unit == 0.0); + BOOST_CHECK(comp_double(claim.m_magnitude_unit, 0.0)); BOOST_CHECK(claim.m_signature.empty() == true); @@ -141,7 +161,7 @@ BOOST_AUTO_TEST_CASE(it_initializes_to_the_specified_version) BOOST_CHECK(claim.m_magnitude == 0); BOOST_CHECK(claim.m_research_subsidy == 0); - BOOST_CHECK(claim.m_magnitude_unit == 0.0); + BOOST_CHECK(comp_double(claim.m_magnitude_unit, 0.0)); BOOST_CHECK(claim.m_signature.empty() == true); @@ -220,7 +240,7 @@ BOOST_AUTO_TEST_CASE(it_parses_a_legacy_boincblock_string_for_researcher) BOOST_CHECK(claim.m_magnitude == 123); BOOST_CHECK(claim.m_research_subsidy == 47.25 * COIN); - BOOST_CHECK(claim.m_magnitude_unit == 0.123456); + BOOST_CHECK(comp_double(claim.m_magnitude_unit, 0.123456)); BOOST_CHECK(claim.m_signature == signature); @@ -503,7 +523,7 @@ BOOST_AUTO_TEST_CASE(it_deserializes_from_a_stream_for_investor) BOOST_CHECK(claim.m_research_subsidy == 0); BOOST_CHECK(claim.m_magnitude == 0.0); - BOOST_CHECK(claim.m_magnitude_unit == 0.0); + BOOST_CHECK(comp_double(claim.m_magnitude_unit, 0.0)); BOOST_CHECK(claim.m_signature.empty() == true); BOOST_CHECK(claim.m_quorum_address.empty() == true); BOOST_CHECK(claim.m_superblock->WellFormed() == false); @@ -545,7 +565,7 @@ BOOST_AUTO_TEST_CASE(it_deserializes_from_a_stream_for_investor_with_superblock) BOOST_CHECK(claim.m_research_subsidy == 0); BOOST_CHECK(claim.m_magnitude == 0.0); - BOOST_CHECK(claim.m_magnitude_unit == 0.0); + BOOST_CHECK(comp_double(claim.m_magnitude_unit, 0.0)); BOOST_CHECK(claim.m_signature.empty() == true); } @@ -630,7 +650,7 @@ BOOST_AUTO_TEST_CASE(it_deserializes_from_a_stream_for_researcher) BOOST_CHECK(claim.m_research_subsidy == expected.m_research_subsidy); BOOST_CHECK(claim.m_magnitude == 0.0); - BOOST_CHECK(claim.m_magnitude_unit == 0.0); + BOOST_CHECK(comp_double(claim.m_magnitude_unit, 0.0)); BOOST_CHECK(claim.m_signature == expected.m_signature); BOOST_CHECK(claim.m_quorum_hash == expected.m_quorum_hash); @@ -670,7 +690,7 @@ BOOST_AUTO_TEST_CASE(it_deserializes_from_a_stream_for_researcher_with_superbloc BOOST_CHECK(claim.m_research_subsidy == expected.m_research_subsidy); BOOST_CHECK(claim.m_magnitude == 0.0); - BOOST_CHECK(claim.m_magnitude_unit == 0.0); + BOOST_CHECK(comp_double(claim.m_magnitude_unit, 0.0)); BOOST_CHECK(claim.m_signature == expected.m_signature); BOOST_CHECK(claim.m_quorum_hash == expected.m_quorum_hash); diff --git a/src/test/gridcoin/researcher_tests.cpp b/src/test/gridcoin/researcher_tests.cpp index 352c2b464f..e163fb5862 100644 --- a/src/test/gridcoin/researcher_tests.cpp +++ b/src/test/gridcoin/researcher_tests.cpp @@ -183,6 +183,26 @@ void AddProtocolEntry(const uint32_t& payload_version, const std::string& key, c registry.Add({contract, dummy_tx, &dummy_index}); } + +// Unfortunately, GCC 13 on openSUSE i386 is misbehaving and exhibiting weird errors in the last decimal places for things +// even as straightforward as +// +// double foo = 0.0; +// text >> foo. +// +// This comparison function works around that by allowing a small error band to pass the tests, but not enough to invalidate +// the tests on compilers that work. +bool comp_double(double lhs, double rhs) +{ + // Require exact match if 0=0. + if (std::min(lhs, rhs) == 0.0) { + return (lhs == rhs); + } else { + double unsigned_rel_error = std::abs(lhs - rhs) / std::min(lhs, rhs); + + return (unsigned_rel_error <= double {1e-8}); + } +} } // anonymous namespace // ----------------------------------------------------------------------------- @@ -205,7 +225,7 @@ BOOST_AUTO_TEST_CASE(it_initializes_with_project_data) BOOST_CHECK(project.m_cpid == expected); BOOST_CHECK(project.m_team == "team name"); BOOST_CHECK(project.m_url == "url"); - BOOST_CHECK(project.m_rac == 0.0); + BOOST_CHECK(comp_double(project.m_rac, 0.0)); BOOST_CHECK(project.m_error == GRC::MiningProject::Error::NONE); } @@ -234,7 +254,7 @@ BOOST_AUTO_TEST_CASE(it_parses_a_project_xml_string) BOOST_CHECK(project.m_cpid == cpid); BOOST_CHECK(project.m_team == "team name"); BOOST_CHECK(project.m_url == "https://example.com/"); - BOOST_CHECK(project.m_rac == 123.45); + BOOST_CHECK(comp_double(project.m_rac, 123.45)); BOOST_CHECK(project.m_error == GRC::MiningProject::Error::NONE); // Clean up: @@ -269,7 +289,7 @@ BOOST_AUTO_TEST_CASE(it_falls_back_to_compute_a_missing_external_cpid) BOOST_CHECK(project.m_cpid == cpid); BOOST_CHECK(project.m_team == "team name"); BOOST_CHECK(project.m_url == "https://example.com/"); - BOOST_CHECK(project.m_rac == 123.45); + BOOST_CHECK(comp_double(project.m_rac, 123.45)); BOOST_CHECK(project.m_error == GRC::MiningProject::Error::NONE); // Clean up: @@ -488,7 +508,7 @@ BOOST_AUTO_TEST_CASE(it_parses_a_set_of_project_xml_sections) BOOST_CHECK(project1->m_cpid == cpid_1); BOOST_CHECK(project1->m_team == "gridcoin"); BOOST_CHECK(project1->m_url == "https://example.com/1"); - BOOST_CHECK(project1->m_rac == 123.45); + BOOST_CHECK(comp_double(project1->m_rac, 123.45)); BOOST_CHECK(project1->m_error == GRC::MiningProject::Error::NONE); BOOST_CHECK(project1->Eligible() == true); } else { @@ -500,7 +520,7 @@ BOOST_AUTO_TEST_CASE(it_parses_a_set_of_project_xml_sections) BOOST_CHECK(project2->m_cpid == cpid_2); BOOST_CHECK(project2->m_team == "gridcoin"); BOOST_CHECK(project2->m_url == "https://example.com/2"); - BOOST_CHECK(project2->m_rac == 567.89); + BOOST_CHECK(comp_double(project2->m_rac, 567.89)); BOOST_CHECK(project2->m_error == GRC::MiningProject::Error::NONE); BOOST_CHECK(project2->Eligible() == true); } else { @@ -855,7 +875,7 @@ BOOST_AUTO_TEST_CASE(it_parses_project_xml_to_a_global_researcher_singleton) BOOST_CHECK(project1->m_cpid == cpid_1); BOOST_CHECK(project1->m_team == "gridcoin"); BOOST_CHECK(project1->m_url == "https://example.com/1"); - BOOST_CHECK(project1->m_rac == 1.1); + BOOST_CHECK(comp_double(project1->m_rac, 1.1)); BOOST_CHECK(project1->m_error == GRC::MiningProject::Error::NONE); BOOST_CHECK(project1->Eligible() == true); } else { @@ -867,7 +887,7 @@ BOOST_AUTO_TEST_CASE(it_parses_project_xml_to_a_global_researcher_singleton) BOOST_CHECK(project2->m_cpid == cpid_2); BOOST_CHECK(project2->m_team == "gridcoin"); BOOST_CHECK(project2->m_url == "https://example.com/2"); - BOOST_CHECK(project2->m_rac == 2.2); + BOOST_CHECK(comp_double(project2->m_rac, 2.2)); BOOST_CHECK(project2->m_error == GRC::MiningProject::Error::NONE); BOOST_CHECK(project2->Eligible() == true); } else { @@ -909,7 +929,7 @@ BOOST_AUTO_TEST_CASE(it_looks_up_loaded_boinc_projects_by_name) BOOST_CHECK(project->m_cpid == cpid); BOOST_CHECK(project->m_team == "gridcoin"); BOOST_CHECK(project->m_url == "https://example.com/"); - BOOST_CHECK(project->m_rac == 1.1); + BOOST_CHECK(comp_double(project->m_rac, 1.1)); BOOST_CHECK(project->m_error == GRC::MiningProject::Error::NONE); BOOST_CHECK(project->Eligible() == true); } else { @@ -1048,7 +1068,7 @@ BOOST_AUTO_TEST_CASE(it_tags_invalid_projects_with_errors_when_parsing_xml) BOOST_CHECK(project1->m_name == "project name 1"); BOOST_CHECK(project1->m_cpid == cpid); BOOST_CHECK(project1->m_team == "not gridcoin"); - BOOST_CHECK(project1->m_rac == 1.1); + BOOST_CHECK(comp_double(project1->m_rac, 1.1)); BOOST_CHECK(project1->m_error == GRC::MiningProject::Error::INVALID_TEAM); BOOST_CHECK(project1->Eligible() == false); } else { @@ -1059,7 +1079,7 @@ BOOST_AUTO_TEST_CASE(it_tags_invalid_projects_with_errors_when_parsing_xml) BOOST_CHECK(project2->m_name == "project name 2"); BOOST_CHECK(project2->m_cpid == cpid); BOOST_CHECK(project2->m_team.empty() == true); - BOOST_CHECK(project2->m_rac == 2.2); + BOOST_CHECK(comp_double(project2->m_rac, 2.2)); BOOST_CHECK(project2->m_error == GRC::MiningProject::Error::INVALID_TEAM); BOOST_CHECK(project2->Eligible() == false); } else { @@ -1070,7 +1090,7 @@ BOOST_AUTO_TEST_CASE(it_tags_invalid_projects_with_errors_when_parsing_xml) BOOST_CHECK(project3->m_name == "project name 3"); BOOST_CHECK(project3->m_cpid == GRC::Cpid()); BOOST_CHECK(project3->m_team == "gridcoin"); - BOOST_CHECK(project3->m_rac == 3.3); + BOOST_CHECK(comp_double(project3->m_rac, 3.3)); BOOST_CHECK(project3->m_error == GRC::MiningProject::Error::MALFORMED_CPID); BOOST_CHECK(project3->Eligible() == false); } else { @@ -1081,7 +1101,7 @@ BOOST_AUTO_TEST_CASE(it_tags_invalid_projects_with_errors_when_parsing_xml) BOOST_CHECK(project4->m_name == "project name 4"); BOOST_CHECK(project4->m_cpid == GRC::Cpid()); BOOST_CHECK(project4->m_team == "gridcoin"); - BOOST_CHECK(project4->m_rac == 4.4); + BOOST_CHECK(comp_double(project4->m_rac, 4.4)); BOOST_CHECK(project4->m_error == GRC::MiningProject::Error::MALFORMED_CPID); BOOST_CHECK(project4->Eligible() == false); } else { @@ -1092,7 +1112,7 @@ BOOST_AUTO_TEST_CASE(it_tags_invalid_projects_with_errors_when_parsing_xml) BOOST_CHECK(project5->m_name == "project name 5"); BOOST_CHECK(project5->m_cpid == cpid); BOOST_CHECK(project5->m_team == "gridcoin"); - BOOST_CHECK(project5->m_rac == 5.5); + BOOST_CHECK(comp_double(project5->m_rac, 5.5)); BOOST_CHECK(project5->m_error == GRC::MiningProject::Error::MISMATCHED_CPID); BOOST_CHECK(project5->Eligible() == false); } else { @@ -1103,7 +1123,7 @@ BOOST_AUTO_TEST_CASE(it_tags_invalid_projects_with_errors_when_parsing_xml) BOOST_CHECK(project6->m_name == "project name 6"); BOOST_CHECK(project6->m_cpid == cpid); BOOST_CHECK(project6->m_team == "gridcoin"); - BOOST_CHECK(project6->m_rac == 6.6); + BOOST_CHECK(comp_double(project6->m_rac, 6.6)); BOOST_CHECK(project6->m_error == GRC::MiningProject::Error::MISMATCHED_CPID); BOOST_CHECK(project6->Eligible() == false); } else { @@ -1112,7 +1132,7 @@ BOOST_AUTO_TEST_CASE(it_tags_invalid_projects_with_errors_when_parsing_xml) if (const GRC::ProjectOption project7 = projects.Try("project name 7")) { BOOST_CHECK(project7->m_name == "project name 7"); - BOOST_CHECK(project7->m_rac == 7.7); + BOOST_CHECK(comp_double(project7->m_rac, 7.7)); BOOST_CHECK(project7->m_error == GRC::MiningProject::Error::POOL); BOOST_CHECK(project7->Eligible() == false); } else { @@ -1122,7 +1142,7 @@ BOOST_AUTO_TEST_CASE(it_tags_invalid_projects_with_errors_when_parsing_xml) if (const GRC::ProjectOption project8 = projects.Try("project name 8")) { BOOST_CHECK(project8->m_name == "project name 8"); BOOST_CHECK(project8->m_cpid.IsZero() == true); - BOOST_CHECK(project8->m_rac == 8.8); + BOOST_CHECK(comp_double(project8->m_rac, 8.8)); BOOST_CHECK(project8->m_error == GRC::MiningProject::Error::POOL); BOOST_CHECK(project8->Eligible() == false); } else { @@ -1133,7 +1153,7 @@ BOOST_AUTO_TEST_CASE(it_tags_invalid_projects_with_errors_when_parsing_xml) BOOST_CHECK(project9->m_name == "project name 9"); BOOST_CHECK(project9->m_cpid == cpid); BOOST_CHECK(project9->m_team == "not gridcoin"); - BOOST_CHECK(project9->m_rac == 0.0); + BOOST_CHECK(comp_double(project9->m_rac, 0.0)); BOOST_CHECK(project9->m_error == GRC::MiningProject::Error::INVALID_TEAM); BOOST_CHECK(project9->Eligible() == false); } else { @@ -1212,7 +1232,7 @@ BOOST_AUTO_TEST_CASE(it_skips_the_team_requirement_when_set_by_protocol) BOOST_CHECK(project1->m_name == "project name 1"); BOOST_CHECK(project1->m_cpid == cpid); BOOST_CHECK(project1->m_team == "! not gridcoin !"); - BOOST_CHECK(project1->m_rac == 1.1); + BOOST_CHECK(comp_double(project1->m_rac, 1.1)); BOOST_CHECK(project1->m_error == GRC::MiningProject::Error::NONE); BOOST_CHECK(project1->Eligible() == true); } else { @@ -1282,7 +1302,7 @@ BOOST_AUTO_TEST_CASE(it_applies_the_team_whitelist_when_set_by_the_protocol) BOOST_CHECK(project1->m_name == "project name 1"); BOOST_CHECK(project1->m_cpid == cpid); BOOST_CHECK(project1->m_team == "! not gridcoin !"); - BOOST_CHECK(project1->m_rac == 1.1); + BOOST_CHECK(comp_double(project1->m_rac, 1.1)); BOOST_CHECK(project1->m_error == GRC::MiningProject::Error::INVALID_TEAM); BOOST_CHECK(project1->Eligible() == false); } else { @@ -1293,7 +1313,7 @@ BOOST_AUTO_TEST_CASE(it_applies_the_team_whitelist_when_set_by_the_protocol) BOOST_CHECK(project2->m_name == "project name 2"); BOOST_CHECK(project2->m_cpid == cpid); BOOST_CHECK(project2->m_team == "team 1"); - BOOST_CHECK(project2->m_rac == 0); + BOOST_CHECK(comp_double(project2->m_rac, 0)); BOOST_CHECK(project2->m_error == GRC::MiningProject::Error::NONE); BOOST_CHECK(project2->Eligible() == true); } else { @@ -1304,7 +1324,7 @@ BOOST_AUTO_TEST_CASE(it_applies_the_team_whitelist_when_set_by_the_protocol) BOOST_CHECK(project3->m_name == "project name 3"); BOOST_CHECK(project3->m_cpid == cpid); BOOST_CHECK(project3->m_team == "team 2"); - BOOST_CHECK(project3->m_rac == 0); + BOOST_CHECK(comp_double(project3->m_rac, 0)); BOOST_CHECK(project3->m_error == GRC::MiningProject::Error::NONE); BOOST_CHECK(project3->Eligible() == true); } else { @@ -1629,7 +1649,7 @@ void it_parses_project_xml_from_a_client_state_xml_file() BOOST_CHECK(project1->m_name == "valid project 1"); BOOST_CHECK(project1->m_cpid == cpid_1); BOOST_CHECK(project1->m_team == "gridcoin"); - BOOST_CHECK(project1->m_rac == 1.1); + BOOST_CHECK(comp_double(project1->m_rac, 1.1)); BOOST_CHECK(project1->m_url == "https://project1.example.com/boinc/"); BOOST_CHECK(project1->m_error == GRC::MiningProject::Error::NONE); BOOST_CHECK(project1->Eligible() == true); @@ -1641,7 +1661,7 @@ void it_parses_project_xml_from_a_client_state_xml_file() BOOST_CHECK(project2->m_name == "valid project 2"); BOOST_CHECK(project2->m_cpid == cpid_2); BOOST_CHECK(project2->m_team == "gridcoin"); - BOOST_CHECK(project2->m_rac == 2.2); + BOOST_CHECK(comp_double(project2->m_rac, 2.2)); BOOST_CHECK(project2->m_url == "https://project2.example.com/boinc/"); BOOST_CHECK(project2->m_error == GRC::MiningProject::Error::NONE); BOOST_CHECK(project2->Eligible() == true); @@ -1654,7 +1674,7 @@ void it_parses_project_xml_from_a_client_state_xml_file() BOOST_CHECK(project3->m_name == "invalid project 3"); BOOST_CHECK(project3->m_cpid == cpid_2); BOOST_CHECK(project3->m_team == "gridcoin"); - BOOST_CHECK(project3->m_rac == 3.3); + BOOST_CHECK(comp_double(project3->m_rac, 3.3)); BOOST_CHECK(project3->m_url == "https://project3.example.com/boinc/"); BOOST_CHECK(project3->m_error == GRC::MiningProject::Error::MISMATCHED_CPID); BOOST_CHECK(project3->Eligible() == false); From 639b28b6c497f82d9b13655d8b7e63cc234ef885 Mon Sep 17 00:00:00 2001 From: div72 Date: Sat, 24 Feb 2024 18:49:02 +0300 Subject: [PATCH 40/44] ci: change Qt path in CMake CI Homebrew seems to have changed the path for the Qt files which we were relying on. --- .github/workflows/cmake-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-ci.yml b/.github/workflows/cmake-ci.yml index dd34e2d624..4105710601 100644 --- a/.github/workflows/cmake-ci.yml +++ b/.github/workflows/cmake-ci.yml @@ -131,7 +131,7 @@ jobs: qt@5 options: >- -DENABLE_GUI=ON - -DQt5_DIR=/usr/local/opt/qt5/lib/cmake/Qt5 + -DQt5_DIR=/usr/local/opt/qt@5/lib/cmake/Qt5 -DENABLE_QRENCODE=ON -DENABLE_UPNP=ON - tag: system-libs From 18154913d298750ddee15850a67424f23600de99 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Fri, 23 Feb 2024 14:59:04 -0500 Subject: [PATCH 41/44] Implement poll field length limiters in GUI form --- src/gridcoin/voting/builders.cpp | 8 ++--- src/gridcoin/voting/poll.h | 14 ++++++--- src/qt/voting/pollwizarddetailspage.cpp | 39 +++++++++++++++++++++++++ src/qt/voting/pollwizardprojectpage.cpp | 3 ++ src/qt/voting/votingmodel.cpp | 36 +++++++++++++++++++++++ src/qt/voting/votingmodel.h | 4 +++ 6 files changed, 96 insertions(+), 8 deletions(-) diff --git a/src/gridcoin/voting/builders.cpp b/src/gridcoin/voting/builders.cpp index 676316d3f1..529a883028 100644 --- a/src/gridcoin/voting/builders.cpp +++ b/src/gridcoin/voting/builders.cpp @@ -1158,19 +1158,19 @@ PollBuilder PollBuilder::AddAdditionalField(Poll::AdditionalField field) ToString(POLL_MAX_ADDITIONAL_FIELDS_SIZE))); } - if (field.m_name.size() > Poll::AdditionalField::MAX_N_OR_V_SIZE) { + if (field.m_name.size() > Poll::AdditionalField::MAX_NAME_SIZE) { throw VotingError(strprintf( _("Poll additional field name \"%s\" exceeds %s characters."), field.m_name, - ToString(Poll::AdditionalField::MAX_N_OR_V_SIZE))); + ToString(Poll::AdditionalField::MAX_NAME_SIZE))); } - if (field.m_value.size() > Poll::AdditionalField::MAX_N_OR_V_SIZE) { + if (field.m_value.size() > Poll::AdditionalField::MAX_VALUE_SIZE) { throw VotingError(strprintf( _("Poll additional field value \"%s\" for field name \"%s\" exceeds %s characters."), field.m_value, field.m_name, - ToString(Poll::AdditionalField::MAX_N_OR_V_SIZE))); + ToString(Poll::AdditionalField::MAX_VALUE_SIZE))); } if (m_poll->m_additional_fields.FieldExists(field.m_name)) { diff --git a/src/gridcoin/voting/poll.h b/src/gridcoin/voting/poll.h index d05cea18a6..1decaae541 100644 --- a/src/gridcoin/voting/poll.h +++ b/src/gridcoin/voting/poll.h @@ -203,9 +203,15 @@ class Poll { public: //! - //! \brief The maximum length for a poll additional field name or value. + //! \brief The maximum length for a poll additional field name. //! - static constexpr size_t MAX_N_OR_V_SIZE = 100; + static constexpr size_t MAX_NAME_SIZE = 100; + + //! + //! \brief The maximum length for a poll additional field value. This is currently set to align with the + //! maximum Project URL length. + //! + static constexpr size_t MAX_VALUE_SIZE = 500; std::string m_name; std::string m_value; @@ -244,8 +250,8 @@ class Poll template inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(LIMITED_STRING(m_name, MAX_N_OR_V_SIZE)); - READWRITE(LIMITED_STRING(m_value, MAX_N_OR_V_SIZE)); + READWRITE(LIMITED_STRING(m_name, MAX_NAME_SIZE)); + READWRITE(LIMITED_STRING(m_value, MAX_VALUE_SIZE)); READWRITE(m_required); } }; // AdditionalField diff --git a/src/qt/voting/pollwizarddetailspage.cpp b/src/qt/voting/pollwizarddetailspage.cpp index c282ffecaa..1e75926e76 100644 --- a/src/qt/voting/pollwizarddetailspage.cpp +++ b/src/qt/voting/pollwizarddetailspage.cpp @@ -3,6 +3,7 @@ // file COPYING or https://opensource.org/licenses/mit-license.php. #include "main.h" +#include "qitemdelegate.h" #include "qt/bitcoinunits.h" #include "qt/decoration.h" #include "qt/forms/voting/ui_pollwizarddetailspage.h" @@ -54,6 +55,37 @@ class ChoicesListDelegate : public QStyledItemDelegate } }; // ChoicesListDelegate +//! +//! \brief Applies custom behavior to additional field items in the poll editor. +//! +class AdditionalFieldDelegate : public QItemDelegate +{ + Q_OBJECT + +public: + AdditionalFieldDelegate(QObject* parent = nullptr) : QItemDelegate(parent) + { + } + + QWidget* createEditor( + QWidget* parent, + const QStyleOptionViewItem& option, + const QModelIndex& index) const override + { + QWidget* editor = QItemDelegate::createEditor(parent, option, index); + + if (QLineEdit* line_edit = qobject_cast(editor)) { + if (index.column() == AdditionalFieldsTableModel::Name) { + line_edit->setMaxLength(VotingModel::maxPollAdditionalFieldNameLength()); + } else if (index.column() == AdditionalFieldsTableModel::Value) { + line_edit->setMaxLength(VotingModel::maxPollAdditionalFieldValueLength()); + } + } + + return editor; + } +}; // AdditionalFieldDelegate + //! //! \brief Provides for QWizardPage::registerField() without a real widget. //! @@ -167,6 +199,7 @@ PollWizardDetailsPage::PollWizardDetailsPage(QWidget* parent) ui->responseTypeList->addItem(tr("Multiple Choice")); ChoicesListDelegate* choices_delegate = new ChoicesListDelegate(this); + AdditionalFieldDelegate* additonal_field_delegate = new AdditionalFieldDelegate(this); ui->choicesList->setModel(m_choices_model.get()); ui->choicesList->setItemDelegate(choices_delegate); @@ -174,6 +207,12 @@ PollWizardDetailsPage::PollWizardDetailsPage(QWidget* parent) ui->editChoiceButton->hide(); ui->removeChoiceButton->hide(); + ui->additionalFieldsTableView->setItemDelegate(additonal_field_delegate); + + ui->titleField->setMaxLength(m_voting_model->maxPollTitleLength()); + ui->questionField->setMaxLength(m_voting_model->maxPollQuestionLength()); + ui->urlField->setMaxLength(m_voting_model->maxPollUrlLength()); + connect( ui->responseTypeList, QOverload::of(&QComboBox::currentIndexChanged), this, [=](int index) { diff --git a/src/qt/voting/pollwizardprojectpage.cpp b/src/qt/voting/pollwizardprojectpage.cpp index f825155be5..1b509d3218 100644 --- a/src/qt/voting/pollwizardprojectpage.cpp +++ b/src/qt/voting/pollwizardprojectpage.cpp @@ -31,6 +31,9 @@ PollWizardProjectPage::PollWizardProjectPage(QWidget* parent) ui->removeWidget->hide(); ui->addRemoveStateLineEdit->hide(); + ui->projectNameField->setMaxLength(m_voting_model->maxPollProjectNameLength()); + ui->projectUrlField->setMaxLength(m_voting_model->maxPollProjectUrlLength()); + QStringListModel* project_names_model = new QStringListModel(this); QStringListModel* project_urls_model = new QStringListModel(this); diff --git a/src/qt/voting/votingmodel.cpp b/src/qt/voting/votingmodel.cpp index 2efed942a7..dc55983262 100644 --- a/src/qt/voting/votingmodel.cpp +++ b/src/qt/voting/votingmodel.cpp @@ -217,6 +217,42 @@ int VotingModel::maxPollChoiceLabelLength() return Poll::Choice::MAX_LABEL_SIZE; } +int VotingModel::maxPollAdditionalFieldNameLength() +{ + // Not strictly accurate: the protocol limits the max length in bytes, but + // Qt limits field lengths in UTF-8 characters which may be represented by + // more than one byte. + // + return Poll::AdditionalField::MAX_NAME_SIZE; +} + +int VotingModel::maxPollAdditionalFieldValueLength() +{ + // Not strictly accurate: the protocol limits the max length in bytes, but + // Qt limits field lengths in UTF-8 characters which may be represented by + // more than one byte. + // + return Poll::AdditionalField::MAX_VALUE_SIZE; +} + +int VotingModel::maxPollProjectNameLength() +{ + // Not strictly accurate: the protocol limits the max length in bytes, but + // Qt limits field lengths in UTF-8 characters which may be represented by + // more than one byte. + // + return Project::MAX_NAME_SIZE; +} + +int VotingModel::maxPollProjectUrlLength() +{ + // Not strictly accurate: the protocol limits the max length in bytes, but + // Qt limits field lengths in UTF-8 characters which may be represented by + // more than one byte. + // + return Project::MAX_URL_SIZE; +} + OptionsModel& VotingModel::getOptionsModel() { return m_options_model; diff --git a/src/qt/voting/votingmodel.h b/src/qt/voting/votingmodel.h index f207948ecc..435eef240a 100644 --- a/src/qt/voting/votingmodel.h +++ b/src/qt/voting/votingmodel.h @@ -130,6 +130,10 @@ class VotingModel : public QObject static int maxPollUrlLength(); static int maxPollQuestionLength(); static int maxPollChoiceLabelLength(); + static int maxPollAdditionalFieldNameLength(); + static int maxPollAdditionalFieldValueLength(); + static int maxPollProjectNameLength(); + static int maxPollProjectUrlLength(); OptionsModel& getOptionsModel(); QString getCurrentPollTitle() const; From 419d827ea6623df580835707c09cb221867ef673 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sat, 24 Feb 2024 23:40:37 -0500 Subject: [PATCH 42/44] Correct -tor argument handling --- src/init.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 286d5d11eb..958c536106 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1144,15 +1144,22 @@ bool AppInit2(ThreadHandlerPtr threads) } // -tor can override normal proxy, -notor disables Tor entirely - if (gArgs.IsArgSet("-tor") && (fProxy || gArgs.IsArgSet("-tor"))) { - proxyType addrOnion; - if (!gArgs.IsArgSet("-tor")) { - addrOnion = addrProxy; + if (gArgs.IsArgSet("-tor")) { + CService addrOnion; + + // If -tor is specified without any argument, and proxy was specified, then override proxy with tor + // at same address and port. + if (gArgs.GetArg("-tor", "") == "") { + if (fProxy) { + addrOnion = addrProxy; + } } else { - CService addrProxy(LookupNumeric(gArgs.GetArg("-tor", "").c_str(), 9050)); + addrOnion = CService(LookupNumeric(gArgs.GetArg("-tor", "").c_str(), 9050)); } - if (!addrOnion.IsValid()) + + if (!addrOnion.IsValid()) { return InitError(strprintf(_("Invalid -tor address: '%s'"), gArgs.GetArg("-tor", ""))); + } SetProxy(NET_TOR, addrOnion); SetReachable(NET_TOR, true); } From 076362def6c1ecd8f6dcd33cc2febe52d2257e03 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Mon, 26 Feb 2024 22:39:56 -0500 Subject: [PATCH 43/44] Change -tor bad parameter error message Co-authored-by: div72 <60045611+div72@users.noreply.github.com> --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 958c536106..5cb0bff00c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1158,7 +1158,7 @@ bool AppInit2(ThreadHandlerPtr threads) } if (!addrOnion.IsValid()) { - return InitError(strprintf(_("Invalid -tor address: '%s'"), gArgs.GetArg("-tor", ""))); + return InitError(strprintf(_("Invalid -tor address: '%s'"), gArgs.GetArg("-tor", gArgs.GetArg("-proxy", "")))); } SetProxy(NET_TOR, addrOnion); SetReachable(NET_TOR, true); From 06e8c414a29d66a111fb0d2ea4b74e0d3a8b8643 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Thu, 29 Feb 2024 17:38:13 -0500 Subject: [PATCH 44/44] translation updates --- src/qt/locale/bitcoin_de.ts | 142 ++- src/qt/locale/bitcoin_pt_PT.ts | 2051 +++----------------------------- src/qt/locale/bitcoin_vi.ts | 375 +++++- 3 files changed, 663 insertions(+), 1905 deletions(-) diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index fb6bd84a62..dcc5012ea8 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -12,7 +12,11 @@ Value Wert - + + Required + Erforderlich + + AddressBookPage @@ -63,6 +67,10 @@ These are your Gridcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. Das sind Ihre Gridcoin Adressen um Zahlungen zu erhalten. Sie werden vielleicht verschiedene an jeden Sender vergeben, damit Sie im Auge behalten können wer sie bezahlt. + + Double-click to edit label + Doppelklicken um das Label zu bearbeiten + &Delete &Löschen @@ -79,6 +87,11 @@ Export Address Book Data Exportiere Addressbuch Daten + + Comma separated file + Name of CSV file format + Kommaseparierte Datei + Error exporting Fehler berichten @@ -206,6 +219,13 @@ Warnung: Die Feststelltaste ist aktiviert! + + BanTableModel + + IP/Netmask + IP/Netzmaske + + BitcoinGUI @@ -236,6 +256,10 @@ Show the list of addresses for receiving payments Zeige die Liste der Addressen für die Erhaltung von Zahlungen + + &History + &Historie + Browse transaction history Transaktionsverlauf durchsehen @@ -264,6 +288,14 @@ &Web Site &Webseite + + &GRC Chat Room + &GRC Chatraum + + + GRC Chatroom + GRC Chatraum + Gridcoin rewards distributed computing with BOINC Gridcoin belohnt verteiltest Rechnen mit BOINC @@ -308,6 +340,10 @@ &Encrypt Wallet... Wallet &verschlüsseln... + + Encrypt wallet + Wallet verschlüsseln + &Change Passphrase... Passphrase &ändern... @@ -368,6 +404,10 @@ &Help &Hilfe + + Toggle light/dark mode. + Hell-/Dunkelmodus umschalten. + [testnet] [Testnetz] @@ -446,6 +486,14 @@ Incoming transaction Eingehende Transaktion + + Close Confirmation + Beenden bestätigen + + + Exit the Gridcoin wallet? + Die Gridcoinwallet beenden? + URI handling URI Handhabung @@ -514,6 +562,10 @@ %1 times per %2 %1 Mal pro %2 + + none + keine + ClientModel @@ -552,6 +604,10 @@ Change: Wechselgeld: + + Select All + Alles auswählen + Amount Betrag @@ -682,13 +738,45 @@ ConsolidateUnspentWizardSelectInputsPage + + Address + Adresse + Date Datum + + Confirmations + Bestätigungen + + + Confirmed + Bestätigt + + + Quantity + Anzahl + + + Fee + Gebühr + DiagnosticsDialog + + Diagnostics + Diagnose + + + Close + Schließen + + + Passed + Bestanden + Warning Warnung @@ -777,6 +865,10 @@ Welcome Willkommen + + Error + Fehler + %n GB of free space available @@ -805,6 +897,14 @@ Form Formular + + Nothing here yet... + Noch nichts hier... + + + No results available. + Keine Ergebnisse verfügbar. + Loading... Lade... @@ -852,6 +952,14 @@ Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. Minimiert die Anwendung anstatt sie zu beenden wenn das Fenster geschlossen wird. Wenn dies aktiviert ist, müssen Sie das Programm über "Beenden" im Menü schließen. + + Disable Transaction Notifications + Transaktionsbenachrichtigungen deaktivieren + + + Disable Poll Notifications + Abstimmungsbenachrichtigungen deaktivieren + The user interface language can be set here. This setting will take effect after restarting Gridcoin. Die Sprache der GUI kann hier verändert werden. Die Einstellung wird nach einem Neustart übernommen. @@ -876,6 +984,10 @@ Show only a tray icon after minimizing the window. Nur ein Symbol im Infobereich anzeigen, nachdem das Programmfenster minimiert wurde. + + Start minimized + Minimiert starten + &Minimize to the tray instead of the taskbar In den Infobereich anstatt in die Taskleiste &minimieren @@ -976,6 +1088,17 @@ Schwierigkeit: + + PeerTableModel + + Sent + Gesendet + + + Received + Empfangen + + PollCard @@ -1535,7 +1658,11 @@ WARNING: unknown change address WARNUNG: Unbekannte Wechseladdresse - + + Active + Aktiv + + SendCoinsEntry @@ -2018,12 +2145,23 @@ bis + + VotingModel + + Poll not found. + Abstimmung nicht gefunden. + + VotingPage Sort by... Sortieren nach... + + &Active + &Aktiv + WalletModel diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts index 5388d090ed..d3c4bcc10b 100644 --- a/src/qt/locale/bitcoin_pt_PT.ts +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -1,18 +1,11 @@ - + AboutDialog - About Gridcoin Sobre o Gridcoin - - <b>Gridcoin</b> - <b>Gridcoin</b> - - - This is experimental software. @@ -30,17 +23,14 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em AdditionalFieldsTableDataModel - Name Nome - Value Valor - Required Requerido @@ -48,103 +38,83 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em AddressBookPage - Create a new address Criar um novo endereço - &New &Novo - Copy the currently selected address to the system clipboard Copiar o endereço selecionado para a área de transferência - &Copy &Copiar - Show &QR Code Mostrar Código &QR - Sign a message to prove you own a Gridcoin address Assine a mensagem para provar que possui um endereço Gridcoin - Sign &Message Assinar &Mensagem - Verify a message to ensure it was signed with a specified Gridcoin address Verifica a mensagem para assegurar que foi assinada por um endereço Gridcoin especificado - &Verify Message &Verificar Mensagem - Delete the currently selected address from the list Elimina o endereço selecionado da lista - Address Book Livro de Endereços - These are your Gridcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. Estes são os seus endereços do Gridcoin para receber pagamentos. Pode dar diferentes nomes a cada remetente, para que saiba quem lhe está a pagar. - Double-click to edit label Duplo clique para editar a etiqueta - &Delete &Eliminar - Copy &Label Copiar &Etiqueta - &Edit &Editar - Export Address Book Data Exportar Dados do Livro de Endereços - Comma separated file Name of CSV file format Ficheiro separado por vírgulas - Error exporting Erro ao exportar - Could not write to file %1. Não foi possível escrever para o ficheiro %1. @@ -152,17 +122,14 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em AddressTableModel - Label Etiqueta - Address Endereço - (no label) (sem etiqueta) @@ -170,134 +137,102 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em AskPassphraseDialog - Passphrase Dialog Diálogo da Frase de Segurança - Enter passphrase Insira a frase de segurança - New passphrase Nova frase de segurança - Repeat new passphrase Repita a nova frase de segurança - Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. Serve para desabilitar o envio trivial de dinheiro quando o SO está comprometido. Não fornece uma segurança real. - For staking only Apenas para realizar stake - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. Insira a nova frase de segurança para a carteira. <br/> Por favor, utilize uma frase de segurança de <b>10 ou mais carateres aleatórios,</b> ou <b>oito ou mais palavras</b>. - Encrypt wallet Encriptar carteira - This operation needs your wallet passphrase to unlock the wallet. Esta operação precisa da frase de segurança da sua carteira para desbloqueá-la. - Unlock wallet Desbloquear carteira - Change passphrase Modificar frase de segurança - Enter the old and new passphrase to the wallet. Escreva a frase de segurança da carteira antiga, seguida da nova. - Confirm wallet encryption Confirmar encriptação da carteira - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! Aviso: Se encriptar a sua carteira e perder a frase de segurança, irá <b>PERDER TODAS AS SUAS MOEDAS</b>! - Are you sure you wish to encrypt your wallet? Tem a certeza que deseja encriptar a sua carteira? - - Wallet encrypted Carteira encriptada - Gridcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. O Gridcoin irá agora terminar o processo de encriptação. Lembre-se que encriptar a sua carteira não garante que as suas moedas não possam ser roubadas por um malware que infete o seu computador. - IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. IMPORTANTE: Qualquer cópia de segurança feita ao ficheiro da carteira, deverá ser substituído pelo novo ficheiro, atualmente encriptado na carteira. Por razões de segurança, cópias de segurança não encriptadas efetuadas anteriormente do ficheiro da carteira tornar-se-ão inúteis assim que começar a usar a nova carteira encriptada. - - - - Wallet encryption failed Encriptação da carteira falhou - Wallet encryption failed due to an internal error. Your wallet was not encrypted. A encriptação da carteira falhou devido a um erro interno. A sua carteira não foi encriptada. - - The supplied passphrases do not match. As frases de segurança fornecidas não coincidem. - Wallet unlock failed Desbloqueio da carteira falhou - - The passphrase entered for the wallet decryption was incorrect. A frase de segurança introduzida para a desencriptação da carteira estava incorreta. - Wallet passphrase was successfully changed. A frase de segurança da carteira foi alterada com sucesso. - - Warning: The Caps Lock key is on! Aviso: A tecla Caps Lock está ligada! @@ -305,12 +240,6 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em BanTableModel - - IP/Netmask - IP/Netmask - - - Banned Until Banido Até @@ -318,430 +247,352 @@ Este produto inclui desenvolvimento de software pelo Projeto OpenSSL para uso em BitcoinGUI - A fatal error occurred. Gridcoin can no longer continue safely and will quit. Ocorreu um erro fatal. O Gridcoin não consegue continuar em segurança e irá fechar. - - Gridcoin - Gridcoin - - - Wallet Carteira - &Overview &Resumo - Show general overview of wallet Mostrar resumo geral da carteira - &Send &Enviar - Send coins to a Gridcoin address Enviar moedas para um endereço Gridcoin - &Receive &Receber - Show the list of addresses for receiving payments Mostrar lista de endereços de pagamentos recebidos - &History &Histórico - Browse transaction history Explorar histórico das transações - &Favorites &Favoritos - Edit the list of stored addresses and labels Editar a lista de endereços armazenados e etiquetas - &Voting &Votação - Voting Votação - &Block Explorer &Explorador de Blocos - Block Explorer Explorador de Blocos - &Exchange &Cambiar - - Web Site Sítio Web - &Web Site &Site Web - &GRC Chat Room &Sala de Chat GRC - GRC Chatroom Sala de Chat GRC - - &BOINC - &BOINC - - - Gridcoin rewards distributed computing with BOINC Recompensas Gridcoin distribuídas por computação com o BOINC - E&xit S&air - Quit application Sair da aplicação - &About Gridcoin &Sobre o Gridcoin - Show information about Gridcoin Mostrar informações sobre o Gridcoin - &Diagnostics &Diagnósticos - Diagnostics Diagnósticos - &Options... &Opções... - Modify configuration options for Gridcoin Modificar opções de configuração do Gridcoin - Open config &file... Abrir &ficheiro de configuração... - Open the config file in your standard editor Abrir o ficheiro de configuração no seu editor base - &Researcher Wizard... &Assistente de Pesquisa... - Open BOINC and beacon settings for Gridcoin Abrir definições do BOINC e do beacon para o Gridcoin - &Show / Hide &Mostrar / Ocultar - &Encrypt Wallet... &Encriptar Carteira... - Encrypt wallet Encriptar carteira - &Backup Wallet/Config... &Cópia de Segurança da Carteira/Configuração... - Backup wallet/config to another location Cópia de segurança da carteira/configuração para outra localização - &Change Passphrase... &Alterar Frase de Segurança... - Change the passphrase used for wallet encryption Alterar a frase de segurança utilizada na encriptação da carteira - &Unlock Wallet... &Desbloquear Carteira... - Unlock wallet Desbloquear carteira - &Lock Wallet &Bloquear Carteira - Lock wallet Bloquear carteira - Sign &message... Assinar &mensagem... - &Verify message... &Verificar mensagem... - &Export... &Exportar... - Export the data in the current tab to a file Exportar os dados na aba atual para um ficheiro - &Debug window &Janela de Depuração - Open debugging and diagnostic console Abrir consola de diagnóstico e depuração - &Snapshot Download Transferência do &Snapshot - Download and apply latest snapshot Transferir e aplicar o último snapshot - &Reset blockchain data &Repor dados da cadeia de blocos - Remove blockchain data and start chain from zero Remover dados da cadeia de blocos e começar a cadeia do zero - &Mask values &Mascarar valores - Mask the values in the Overview screen Mascarar os valores no ecrã de Visão Geral - &File &Ficheiro - &Settings &Configurações - &Community &Comunidade - &Help &Ajuda - Open menu. Abrir menu. - Toggle light/dark mode. Trocar modo claro/escuro. - Not staking: Miner is not initialized. Não realizando stake: Mineração não foi inicializada. - Not staking: Disabled by configuration. Não realizando stake: Desabilitado por configuração. - - [testnet] [rede de testes] - - Gridcoin client Cliente Gridcoin - No active connections to the Gridcoin network. If this persists more than a few minutes, please check your configuration and your network connectivity. Sem ligações ativas à rede do Gridcoin. Se isto persistir por mais dum que uns minutos, por favor verifique a sua configuração e a conetividade à rede. - %n active connection(s) to the Gridcoin network - %n ligação ativa à rede do Gridcoin%n ligações ativas à rede do Gridcoin%n ligações ativas à rede do Gridcoin + + %n ligação ativa à rede do Gridcoin + %n ligações ativas à rede do Gridcoin + - Sync: no connections. Sincronização: sem conexões - Processed %n block(s) of transaction history. - %n bloco(s) processado(s) do histórico de transações.%n bloco(s) processado(s) do histórico de transações.%n bloco(s) processado(s) do histórico de transações. + + %n bloco(s) processado(s) do histórico de transações. + %n bloco(s) processado(s) do histórico de transações. + - %n second(s) ago - %n segundo(s) atrás%n segundo(s) atrás%n segundo(s) atrás + + %n segundo(s) atrás + %n segundo(s) atrás + - %n minute(s) ago - %n minuto(s) atrás%n minuto(s) atrás%n minuto(s) atrás + + %n minuto(s) atrás + %n minuto(s) atrás + - %n hour(s) ago - %n hora(s) atrás%n hora(s) atrás%n hora(s) atrás + + %n hora(s) atrás + %n hora(s) atrás + - %n day(s) ago - %n dia(s) atrás%n dia(s) atrás%n dia(s) atrás + + %n dia(s) atrás + %n dia(s) atrás + - Up to date Atualizado - Catching up... Recuperando o atraso... - Last received block was generated %1. O último bloco recebido foi gerado há %1. - This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? Esta transação excede o limite de tamanho. Pode continuar a enviar com uma taxa de %1, que vais para os nós que processam a sua transação e ajudam a suportar a rede. Tem a certeza que quer pagar a taxa? - Confirm transaction fee Confirmar taxa de transação - Sent transaction Transação enviada - Incoming transaction Transação recebida - Date: %1 Amount: %2 Type: %3 @@ -752,173 +603,134 @@ Tipo: %3 Endereço: %4 - Do you wish to download and apply the latest snapshot? If yes the wallet will shutdown and perform the task. Quer transferir e aplicar o último snapshot? Se sim, a carteira irá encerrar e executar a tarefa. - Warning: Canceling after stage 2 will result in sync from 0 or corrupted blockchain files. - Aviso: Cancelar depois do 2º passo irá resultar em sincronizar tudo do "0", ou ficheiros corrompidos na cadeia de blocos. + Aviso: Cancelar depois do 2º passo irá resultar em sincronizar tudo do "0", ou ficheiros corrompidos na cadeia de blocos. - Do you want to delete blockchain data and sync from zero? Tem a certeza que quer eliminar os dados da cadeia de blocos e começar a sincronização do zero? - Warning: After the blockchain data is deleted, the wallet will shutdown and when restarted will begin syncing from zero. Your balance will temporarily show as 0 GRC while syncing. Aviso: Depois dos dados da cadeia de blocos serem eliminados, a carteira irá encerrar e ao reiniciar, irá começar a sincronizar do zero. O seu balanço irá temporariamente aparecer como 0 GRC enquanto sincroniza. - Close Confirmation Fechar Confirmação - Exit the Gridcoin wallet? Fechar a carteira Gridcoin? - - URI handling Tratamento do URI - - URI can not be parsed! This can be caused by an invalid Gridcoin address or malformed URI parameters. O URI não pode ser analisado! Isto pode ser causado por um endereço inválido de Gridcoin ou parâmetros de URI mal formados. - Wallet is <b>not encrypted</b>! A Carteira está <b>não encriptada</b>! - Wallet is <b>encrypted</b> and currently %1 A Carteira está <b>encriptada</b> e atualmente %1 - <b>unlocked for staking only</b> <b>desbloqueada para realizar stake apenas</b> - <b>fully unlocked</b> <b>completamente desbloqueada</b> - Wallet is <b>encrypted</b> and currently <b>locked</b> A carteira está <b>encriptada</b> e atualmente <b>bloqueada</b> - Backup Wallet Cópia de Segurança da Carteira - Wallet Data (*.dat) Dados da Carteira (*.dat) - - Backup Failed Cópia de Segurança Falhou - - There was an error trying to save the wallet data to the new location. Houve um erro ao tentar guardar os dados da carteira para uma nova localização. - Backup Config Configuração da Cópia de Segurança - Wallet Config (*.conf) Configuração da Carteira (*.conf) - not available indisponível - year ano - month mês - day dia - hour hora - %1 times per %2 %1 vezes por %2 - Staking.<br>Your weight is %1<br>Network weight is %2<br><b>Estimated</b> staking frequency is %3. A realizar stake. <br>O seu peso é %1<br>Peso da rede é %2<br><b>Frequência</b> estimada de stake é de %3. - Unable to stake: %1 Impossível de realizar stake: %1 - Not staking currently: %1, <b>Estimated</b> staking frequency is %2. Não está a realizar stake atualmente: %1, <b>Frequência</b> estimada de stake é de %2. - - - none nenhum - Scraper: waiting on wallet to sync. Scraper: aguardando que a carteira sincronize. - Scraper: superblock not needed - inactive. Scraper: superbloco desnecessário - inativo - Scraper: downloading and processing stats. Scraper: transferindo e processando estado. - Scraper: Convergence achieved, date/time %1 UTC. Project(s) excluded: %2. Scrapers included: %3. @@ -931,26 +743,22 @@ Scrapers excluídos: %4. Scrapers a não produzir: %5. - Scraper: Convergence achieved, date/time %1 UTC. Project(s) excluded: %2. Scraper: Convergência alcançada, data/hora %1 UTC. Projeto(s) excluído(s): %2. - Scraper: No convergence able to be achieved. Will retry in a few minutes. Scraper: Convergência não alcançada. Irá tentar novamente em alguns minutos. - CPID: %1 Time left to activate: %2%3 CPID: %1 Tempo restante para ativar: %2%3 - CPID: %1 Beacon age: %2 Current beacon expired! @@ -961,7 +769,6 @@ Idade do Beacon: %2 %3 - CPID: %1 Beacon age: %2 Expires: %3 @@ -972,12 +779,10 @@ Expira: %3 %4 - New Poll Nova Sondagem - A new poll is available. Open Gridcoin to vote. Uma nova sondagem está disponível. Abra o Gridcoin para votar. @@ -985,17 +790,14 @@ Expira: %3 ClientModel - Network Alert Alerta de Rede - Low difficulty!; Dificuldade baixa!; - Miner: Minerador: @@ -1003,214 +805,162 @@ Expira: %3 CoinControlDialog - Quantity: Quantidade: - - Bytes: - Bytes: - - - Amount: Quantia: - Fee: Taxa: - Coin Control Controlo de Moedas - Low Output: Baixa Produção: - After Fee: Depois da Taxa: - Change: Modificar: - Toggles between selecting all and selecting none. Mudar entre selecionar todos e nenhum. - - Select All Selecionar Todos - Tree &mode &Modo de árvore - Select inputs Selecionar entradas - - <= - <= - - - Filters the already selected inputs. Filtra as entradas já selecionadas. - Filter Filtro - Pushing this button after making a input selection either manually or with the filter will present a destination address list where you specify a single address as the destination for the consolidated output. The send (Pay To) entry will be filled in with this address and you can finish the consolidation by pressing the send button. Ao premir este botão depois de fazer uma seleção de entrada manualmente ou com o filtro, é apresentada uma lista de endereços de destino onde pode especificar um único endereço como destino para a saída consolidada. A entrada de envio (Pagar a) será preenchida com este endereço e pode terminar a consolidação premindo o botão de enviar. - Consolidate Consolidado - The consolidation transaction is ready to send to self. Please press the ok button to go to the send dialog. A transação de consolidação está preparada para ser enviada para si. Por favor, clique no botão de ok para ir para o diálogo de envio. - Ready to consolidate Pronto para consolidar - Amount Quantia - Date Data - Confirmations Confirmações - Confirmed Confirmada - Label Etiqueta - &List mode &Lista de modo - Address Endereço - Copy address Copiar endereço - Copy label Copiar etiqueta - - Copy amount Copiar quantia - Copy transaction ID Copiar ID da transação - Copy quantity Copiar quantidade - Copy fee Copiar taxa - Copy after fee Copiar depois da taxa - Copy bytes Copiar bytes - Copy low output Copiar baixa produção - Copy change Copiar modificação - Flips the filter mode between selecting inputs less than or equal to the provided value (<=) and greater than or equal to the provided value (>=). The filter also automatically limits the number of inputs to %1, in ascending order for <= and descending order for >=. Alterna o modo de filtro entre a seleção de entradas menores ou iguais ao valor fornecido (<=) e maiores ou iguais ao valor fornecido (>=). O filtro também limita automaticamente o número de entradas a %1, em ordem crescente para <= e decrescente para >=. - Select None Não Selecionar Nenhum - DUST INSIGNIFICANTE - yes sim - no não - This label turns red, if the transaction size is bigger than 10000 bytes. This means a fee of at least %1 per kb is required. @@ -1223,7 +973,6 @@ Isto significa que uma taxa de pelos menos %1 por kb é necessária. Pode variar +/- 1Byte por entrada - This label turns red, if any recipient receives an amount smaller than %1. This means a fee of at least %2 is required. @@ -1236,7 +985,6 @@ Isto significa que uma taxa de pelo menos %2 é necessária. Quantias 0.546 vezes menores que o mínimo, são mostradas como INSIGNIFICANTES. - This label turns red, if the change is smaller than %1. This means a fee of at least %2 is required. @@ -1245,18 +993,14 @@ Quantias 0.546 vezes menores que o mínimo, são mostradas como INSIGNIFICANTES. Isto significa que uma taxa de pelo menos %2 é necessária. - - (no label) (sem etiqueta) - change from %1 (%2) alterar de %1 (%2) - (change) (modificar) @@ -1264,27 +1008,22 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ConsolidateUnspentDialog - Consolidate Unspent Outputs (UTXOs) Consolidar Saídas Não Gastas (UTXOs) - Select Destination Address for Consolidation Selecionar Endereço de Destino de Consolidação - Label Etiqueta - Address Endereço - Note: The number of inputs selected for consolidation has been limited to %1 to prevent a transaction failure due to too many inputs. Nota: O número de entradas selecionado para consolidação foi limitado a %1, para prevenir uma falha de transação devido a demasiadas entradas. @@ -1292,7 +1031,6 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ConsolidateUnspentWizard - Consolidate Unspent Transaction Outputs (UTXOs) Consolidar Saídas Não Gastas (UTXOs) @@ -1300,34 +1038,26 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ConsolidateUnspentWizardSelectDestinationPage - WizardPage Página do Assistente - Step 2: Select the destination address for the consolidation transaction. Note that all of the selected inputs will be consolidated to an output on this address. If there is a very small amount of change (due to uncertainty in the fee calculation), it will also be sent to this address. If you selected inputs only from a particular address on the previous page, then that address will already be selected by default. Passo 2: Selecionar o endereço de destino para a transação de consolidação. Note que todas as entradas selecionadas serão consolidadas numa saída neste endereço. Se houver um valor muito pequeno de mudança (devido à incerteza no cálculo da taxa), ele também será enviado para este endereço. Se na página anterior tiver selecionado apenas entradas de um determinado endereço, esse endereço já estará selecionado por defeito. - - Label Etiqueta - - Address Endereço - Currently selected: Selecionado atualmente: - isComplete estáConcluído @@ -1335,144 +1065,98 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ConsolidateUnspentWizardSelectInputsPage - WizardPage Página do Assistente - Step 1: Select the inputs to be consolidated. Remember that the inputs to the consolidation are your unspent outputs (UTXOs) in your wallet. Passo 1: Selecionar as entradas a serem consolidadas. Lembre-se que as entradas para consolidação, são as saídas não gastas (UTXOs) na sua carteira. - - Select All Selecionar Todos - Tree Mode Modo de Árvore - List Mode Modo de Lista - Select inputs Selecionar entradas - - <= - <= - - - Filters the already selected inputs. Filtra as entradas já selecionadas. - Filter Filtro - Amount Quantia - Label Etiqueta - Address Endereço - Date Data - Confirmations Confirmações - Confirmed Confirmada - Quantity Quantidade - - 99999 - 99999 - - - Fee Taxa - - 99.9999 - 99.9999 - - - After Fee Amount Quantia Depois da Taxa - - 999999999.9999 - 999999999.9999 - - - isComplete estáConcluído - Note: The number of inputs selected for consolidation has been limited to %1 to prevent a transaction failure due to too many inputs. Nota: O número de entradas selecionadas para consolidação foi limitado a %1, para prevenir falhas de transação devido a demasiadas entradas. - Note: The number of inputs selected for consolidation is currently more than the limit of %1. Please use the filter or manual selection to reduce the number of inputs to %1 or less to prevent a transaction failure due to too many inputs. Nota: O número de entradas selecionadas para consolidação é atualmente maior que o limite de %1. Por favor utilize o filtro ou seleção manual para reduzir o número de entradas para %1 ou menos, para prevenir uma falha de transação devido a demasiadas entradas. - Select None Não Selecionar Nenhum - - (no label) (sem etiqueta) - change from %1 (%2) alterar de %1 (%2) - (change) (modificar) @@ -1480,62 +1164,38 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ConsolidateUnspentWizardSendPage - WizardPage Página do Assistente - Step 3: Confirm Consolidation Transaction Details. Transaction will be ready to send when Finish is pressed. Passo 3: Confirmar os detalhes da transação de consolidação. A transação estará pronta quando o Terminar for pressionado. - Number of Inputs Número de Entradas - - 999999 - 999999 - - - Transaction Fee Taxa de Transação - - 99.9999 - 99.9999 - - - Amount Quantia - - 999999999.9999 - 999999999.9999 - - - Destination Address Endereço de Destino - address endereço - Destination Address Label Etiqueta do Endereço de Destino - label etiqueta @@ -1543,123 +1203,98 @@ Isto significa que uma taxa de pelo menos %2 é necessária. DiagnosticsDialog - - Diagnostics Diagnósticos - Verify outbound port works A verificar que as portas de saída estão a funcionar - Check total connections A verificar total de ligaçoes - Verify CPID has active beacon A verificar que o CPID tem um beacon ativo - Verify BOINC path A verificar a diretoria do BOINC - Check outbound connections A verificar ligaçoes de saída - Check difficulty a verificar dificuldade - Verify CPID has RAC A verificar que o CPID tem RAC - Overall Result Resultado Geral - Verify wallet is synced A verificar que a carteira está sincronizada - Verify CPID is valid A verificar que o CPID é válido - Verify clock A verificar data/hora - Check client version A verificar versão do cliente - Check estimated time to stake A verificar tempo estimado para realizar stake - Close Fechar - Test Testar - Testing... Testando... - N/A N/D - Passed Sucesso - Warning Aviso - Failed Falhou - One or more tests have generated a warning status. Wallet operation may be degraded. Please see the individual test tooltips for details and recommended action(s). Um ou mais testes geraram um estado de alerta. Operações com a carteira podem estar corrompidas. Por favor, consulte as dicas individuais de teste para detalhes e ações recomendadas. - One or more tests have failed. Proper wallet operation may be significantly degraded or impossible. Please see the individual test tooltips for details and recommended action(s). Um ou mais testes falharam. Operações adequadas com a carteira, podem estar significativamente degradadas ou impossíveis. Por favor, consulte as dicas individuais de teste para detalhes e ações recomendadas. - All tests passed. Your wallet operation is normal. Todos os testes concluídos. A operação da sua carteira está normal. @@ -1667,67 +1302,54 @@ Isto significa que uma taxa de pelo menos %2 é necessária. EditAddressDialog - Edit Address Editar Endereço - &Label &Etiqueta - The label associated with this address book entry A etiqueta associada a esta entrada do livro de endereços - The address associated with this address book entry. This can only be modified for sending addresses. O endereço associado com esta entrada no livro. Pode ser modificado apenas para endereços de envio. - &Address &Endereço - New receiving address Novo endereço de receção - New sending address Novo endereço de envio - Edit receiving address Editar endereço de receção - Edit sending address Editar endereço de envio - - The entered address "%1" is not a valid Gridcoin address. - O endereço inserido "%1" não é um endereço de Gridcoin válido. + The entered address "%1" is not a valid Gridcoin address. + O endereço inserido "%1" não é um endereço de Gridcoin válido. - - The entered address "%1" is already in the address book. - O endereço introduzido "%1" já se encontra no livro de endereços. + The entered address "%1" is already in the address book. + O endereço introduzido "%1" já se encontra no livro de endereços. - Could not unlock wallet. Não foi possível desbloquear a carteira. - New key generation failed. A criação de uma nova chave falhou. @@ -1735,13 +1357,10 @@ Isto significa que uma taxa de pelo menos %2 é necessária. FavoritesPage - - Favorites Favoritos - Search by address or label Pesquisar por endereço ou etiqueta @@ -1749,7 +1368,6 @@ Isto significa que uma taxa de pelo menos %2 é necessária. Form - Form Formulário @@ -1757,22 +1375,18 @@ Isto significa que uma taxa de pelo menos %2 é necessária. FreespaceChecker - A new data directory will be created. Uma nova diretoria de dados irá ser criada. - Directory already exists. If this directory contains valid data, it will be used. Diretoria já existente. Se esta diretoria tiver dados válidos, será usada. - Path already exists, and is not a directory. Caminho já existente, e não é uma diretoria. - Cannot create data directory here. Não é possível criar diretoria aqui. @@ -1780,133 +1394,109 @@ Isto significa que uma taxa de pelo menos %2 é necessária. GUIUtil::HelpMessageBox - version versão - Usage: Utilização: - command-line options opções da linha de comandos - - - Gridcoin - Gridcoin - - + Intro - Welcome Bem-vindo. - Welcome to %1. Bem-vindo a %1. - As this is the first time the program is launched, you can choose where %1 will store its data. Como é a primeira vez que o programa é lançado, pode escolher onde %1 irá armazenar os dados. - Use the default data directory Utilizar a diretoria de dados predefinida - Use a custom data directory: Utilizar uma diretoria de dados personalizada: - When you click OK, %1 will begin to download and process the full %4 block chain (~%2GB), either from genesis in %3, or the last synchronized block, if this was a preexisting data directory. Quando clicar em OK, %1 começará a transferir e a processar toda a cadeia de blocos %4 (~%2GB), quer a partir da génese em %3, ou a partir do último bloco sincronizado, se este for um diretório de dados pré-existente. - The synchronization is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off. A sincronização é muito exigente e pode expor problemas de hardware do seu computador que anteriormente tivessem passado despercebidos. Cada vez que executar o %1, ele continuará a transferência onde parou anteriormente. - - Gridcoin - Gridcoin + Error: Specified data directory "%1" cannot be created. + Erro: Diretoria de dados especificada "%1" não pode ser criada. - - Error: Specified data directory "%1" cannot be created. - Erro: Diretoria de dados especificada "%1" não pode ser criada. - - - Error Erro - %n GB of free space available - %n GB de espaço livre disponível%n GB de espaço livre disponível%n GB de espaço livre disponível + + %n GB de espaço livre disponível + %n GB de espaço livre disponível + - (of %n GB needed) - (de %n GB necessários)(de %n GB necessários)(de %n GB necessários) + + (de %n GB necessários) + (de %n GB necessários) + - (%n GB needed for full chain) - (de %n GB necessários para cadeia completa)(de %n GB necessários para cadeia completa)(de %n GB necessários para cadeia completa) + + (de %n GB necessários para cadeia completa) + (de %n GB necessários para cadeia completa) + MRCModel - You must have a mature balance of at least 1 GRC to submit an MRC. Tem que ter um balanço com maturidade de pelo menos 1 GRC para poder submeter um pedido de MRC. - Too soon since your last research rewards payment. Muito cedo desde o último pagamento de recompensa de pesquisa. - The total fee (the minimum fee + fee boost) is greater than the rewards due. A taxa total (taxa mínima + taxa de boost) é maior que os ganhos da recompensa. - - Your MRC was successfully submitted earlier but has now become stale without being bound to the just received block by a staker. This may be because your MRC was submitted just before the block was staked and the MRC didn't make it to the staker in time, or your MRC was pushed down in the queue past the pay limit. Please wait for the next block to clear the queue and try again. + Your MRC was successfully submitted earlier but has now become stale without being bound to the just received block by a staker. This may be because your MRC was submitted just before the block was staked and the MRC didn't make it to the staker in time, or your MRC was pushed down in the queue past the pay limit. Please wait for the next block to clear the queue and try again. O seu MRC foi submetido com sucesso mais cedo, mas agora tornou-se obsoleto sem estar ligado ao bloco recém recebido por um staker. Isto pode acontecerr porque o seu MRC foi submetida pouco antes do bloco ter sido staked e o MRC não chegou a tempo ao staker, ou o seu MRC desceu na fila para além do limite de pagamentos. Por favor, aguarde pelo próximo bloco para limpar a fila de espera e tente novamente. - You have a pending MRC request. Tem uma solicitação de MRC pendente. - Your MRC was successfully submitted, but other MRCs with higher fees have pushed your MRC down in the queue past the pay limit, and your MRC will be canceled. Wait until the next block is received and the queue clears and try again. Your fee for the canceled MRC will be refunded. O seu MRC foi submetido com êxito, mas outros MRCs com taxas mais altas, fizeram o seu MRC baixar na fila, ultrapassando o limite de pagamentos, e o seu MRC será cancelado. Aguarde até que o próximo bloco seja recebido e a fila seja limpa e tente novamente. A sua taxa para o MRC cancelado será reembolsada. - The MRC queue is full. You can try boosting your fee to put your MRC request in the queue and displace another MRC request. A fila do MRC está cheia. Pode tentar aumentar a sua taxa para colocar o seu pedido MRC na fila e remover da fila outro pedido de MRC. - The wallet is locked. A carteira está trancada. @@ -1914,150 +1504,106 @@ Isto significa que uma taxa de pelo menos %2 é necessária. MRCRequestPage - MRC Requests Solicitações MRC - Please wait. Por favor aguarde. - MRC Fee @ Pay Limit Position in Queue Taxa MRC @ Posição Limite de Pagamento na Fila - MRC Fee @ Tail of Queue Taxa MRC @ Na Cauda da Fila - Your projected or actual position among MRCs in the memory pool ordered by MRC fee in descending order A sua posição projetada ou real entre os MRCs na reserva de memória, ordenada por taxa de MRC por ordem decrescente - Number of All MRC Requests in Queue Número de Todos os Pedidos MRC na Fila - The number of MRCs in the memory pool Número de pedidos MRC em espera - - - - Your Projected MRC Request Position in Queue A sua posição prevista do seu pedido MRC na fila de espera - The MRC fee being paid by the MRC in the last position within the pay limit in the memory pool A taxa de MRC que está a ser paga pelo MRC na última posição dentro do limite de remuneração na reserva de memória - MRC Request Pay Limit per Block Limite de pagamento por bloco do pedido MRC - Your MRC Calculated Minimum Fee A sua taxa mínima calculada pelo MRC - The calculated minimum fee for the MRC. This may not be sufficient to submit the MRC if the queue is already full. In that case, you need to use the MRC fee boost to raise the fee to get your MRC in the queue. A taxa mínima calculada para o MRC. Este valor pode não ser suficiente para submeter o MRC se a fila de espera já estiver cheia. Nesse caso, é necessário que faça um boost da taxa de MRC para a aumentar, colocando o MRC na fila de espera. - The lowest MRC fee being paid of MRCs in the memory pool A taxa mais baixa de MRC que está a ser paga de MRCs na reserva de memória - The maximum number of MRCs that can be paid per block O número máximo de MRCs que pode ser pago por bloco - The highest MRC fee being paid of MRCs in the memory pool A taxa mais alta de MRC que está a ser paga de MRCs na reserva de memória - MRC Fee @ Head of Queue Taxa MRC @ No Topo da Fila - MRC Fee Boost Aumento da taxa de inscrição no MRC - Raise to Minimum For Submit Subir para o Mínimo para Submeter - Update Atualizar - Submit Submeter - - - - - - - - - - N/A - N/A - - - - - Your Submitted MRC Request Position in Queue A Posição na Fila do Seu Pedido MRC Submetido - You must have an active beacon and the wallet must be in solo mode to submit MRCs. Tem um pedido ativo de beacon e, a carteira tem de estar em modo solo para submeter MRCs. - The block version must be v12 or higher to submit MRCs. A versão do bloco tem de ser v12 ou superior para submeter pedidos MRC. - The wallet must be in sync to submit MRCs. A carteira tem de estar sincronizada para submeter um pedido MRC. - A block update must have occurred after wallet start or sync to submit MRCs. Uma atualização do bloco tem de ocorrer depois da carteira iniciar ou sincronizar, para submeter um pedido MRC. - You must have a mature balance of at least 1 GRC to submit an MRC. Tem que ter um balanço com maturidade de pelo menos 1 GRC para poder submeter um pedido de MRC. @@ -2065,28 +1611,22 @@ Isto significa que uma taxa de pelo menos %2 é necessária. NoResult - Form Formulário - - Nothing here yet... Nada aqui ainda... - No results available. Sem resultados disponíveis. - Loading... Carregando... - Privacy Enabled... Privacidade Habilitada... @@ -2094,294 +1634,226 @@ Isto significa que uma taxa de pelo menos %2 é necessária. OptionsDialog - Options Opções - &Main &Principal - &Network &Rede - Map port using &UPnP Mapear porto utilizando &UPnP - Reserved amount secures a balance in wallet that can be spendable at anytime. However reserve will secure utxo(s) of any size to respect this setting. Quantia reservada assegura um saldo na carteira que pode ser gasto a qualquer altura, No entanto, a reserva irá assegurar utxo(s) de qualquer tamanho para respeitarem estas definições. - Reser&ve Reser&var - Automatically start Gridcoin after logging in to the system. Começar Gridcoin automaticamente depois de entrar no sistema. - &Start Gridcoin on system login &Iniciar Gridcoin no arranque do sistema - Automatically open the Gridcoin client port on the router. This only works when your router supports UPnP and it is enabled. Abre a porta do cliente Gridcoin automaticamente no router. Isto apenas funciona se o seu router suportar UPnP e estiver habilitado. - Pro&xy IP: IP da Pro&xy: - IP address of the proxy (e.g. 127.0.0.1) Endereço IP da proxy (ex: 127.0.0.1) - &Port: &Porto: - Port of the proxy (e.g. 9050) Porto do proxy (ex: 9050) - Staking A realizar stake - This enables or disables staking (the default is enabled). Note that a change to this setting will permanently override the config file with an entry in the settings file. Isto ativa ou desativa o staking (por predefinição está ativado). Note que uma alteração a esta definição irá substituir permanentemente o ficheiro de configuração por uma entrada no ficheiro de definições. - Enable Staking Ativar Staking - This enables or disables splitting of stake outputs to optimize staking (default disabled). Note that a change to this setting will permanently override the config file with an entry in the settings file. Isso permite ativar ou desativar a divisão das saídas de stake para otimizar a aposta (desativado por padrão). Note que uma alteração nesta configuração irá substituir permanentemente o arquivo de configuração com uma entrada no ficheiro de configurações. - Enable Stake Splitting Ativar Divisão de Stake - Target Efficiency Eficiência do Objetivo - - Valid values are between 75 and 98 percent. Note that a change to this setting will permanently override the config file with an entry in the settings file. - Valores válidos estão entre 75 e 98%. Note que uma alteração a esta configuração, irá sobrepor permanentemente o ficheiro de configuração com uma entrada nas definições do ficheiro. - - - Min Post Split UTXO Mínimo Pós-divisão UTXO - Valid values are 800 or greater. Note that a change to this setting will permanently override the config file with an entry in the settings file. Os valores válidos são 800 ou superior. Note que uma alteração a esta definição substituirá permanentemente o ficheiro de configuração por uma entrada no ficheiro de definições. - Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. Minimize em vez sair da aplicação quando a janela é fechada. Com esta opção selecionada, a aplicação apenas será encerrada quando escolher Sair da aplicação no menu. - &Confirm on close &Confirmar ao sair - Disable Transaction Notifications Desabilitar Notificações de Transações - Disable Poll Notifications Desabilitar Notificações de Sondagens - The user interface language can be set here. This setting will take effect after restarting Gridcoin. O idioma da interface de utilizador pode ser definido aqui. Estas definições farão efeito assim que reiniciar o Gridcoin. - Style: Tema: - Choose a stylesheet to change the look of the wallet. Escolha um tema para modificar o aspeto da sua carteira. - Whether to show Gridcoin addresses in the transaction list or not. Mostrar ou não endereços de Gridcoin na lista de transações. - &Display addresses in transaction list &Mostrar endereços na lista de transações - &Window &Janela - &Apply &Aplicar - Show only a tray icon after minimizing the window. Apenas mostrar o ícone na área de notificação após minimizar a janela. - Start minimized Iniciar minimizado - Allow regular checks for updates Permitir verificações regulares por atualizações - Disable &update checks Desabilitar verificações de &atualização - Return change to an input address for contract transactions Devolver o troco para um endereço de entrada para transações de contrato - Connect to the Gridcoin network through a SOCKS5 proxy (e.g. when connecting through Tor). Ligar à rede Gridcoin através de um proxy SOCKS5 (por exemplo, quando a ligação é feita através do Tor). - &Connect through SOCKS5 proxy: &Ligar através de proxy SOCKS5: - &Minimize to the tray instead of the taskbar &Minimizar para a área de notificação e não para a barra de ferramentas - M&inimize on close M&inimizar ao fechar - &Display &Visualização - User Interface &language: &Idioma da interface de utilizador: - &Unit to show amounts in: &Unidade para mostrar quantias: - Choose the default subdivision unit to show in the interface and when sending coins. Escolha a unidade da subdivisão predefinida para ser mostrada na interface e quando enviar as moedas. - Only display transactions on or after Mostrar transações apenas durante ou depois - Setting this will cause the transaction table to only display transactions created on or after this date. Estas definições irão fazer com que a tabela de transações mostre apenas, transações durante ou depois desta data. - - &OK - &OK - - - &Cancel &Cancelar - default por defeito - Dark Escuro - Light Claro - - Warning Aviso - - This setting will take effect after restarting Gridcoin. Estas definições entrarão em efeito depois de reiniciar o Gridcoin. - The supplied proxy address is invalid. O endereço de proxy introduzido é inválido. - The supplied target staking efficiency is invalid. A eficiência de staking do alvo fornecido é inválida. - The supplied minimum post stake-split UTXO size is invalid. O tamanho mínimo de UTXO pós-divisão de stack fornecido é inválido. @@ -2389,185 +1861,122 @@ Isto significa que uma taxa de pelo menos %2 é necessária. OverviewPage - Form Formulário - Available: Disponível: - Your current spendable balance O seu saldo disponível atual - Immature: Imatura: - Wallet Carteira - - The displayed information may be out of date. Your wallet automatically synchronizes with the Gridcoin network after a connection is established, but this process has not completed yet. A informação mostrada pode estar desatualizada. A sua carteira sincroniza automaticamente com a rede Gridcoin depois da ligação ser estabelecida, mas este processo ainda não está completo. - Total of transactions that have yet to be confirmed, and do not yet count toward the current balance Total de transações que têm de ser ainda confirmadas, e ainda não contam para o balanço atual - - Total: - Total: - - - Coin Weight: Peso da Moeda: - Pending Reward: Recompensas Pendentes: - Open the researcher/beacon configuration wizard. Abrir o assistente de configuração do investigador/beacon - Action Needed Ação Necessária - Total mined coins that have not yet matured. Total de moedas mineradas que ainda não estão maduras. - Immature Stake: Stake Imatura: - Amount staked for a recent block that must wait for 110 confirmations to mature before you can spend it. Quantia realizada em stake num bloco recente, que tem de esperar por 110 confirmações antes de poder ser gasta. - Account Overview Visão Geral da Conta - - CPID - CPID - - - - - 0.00 - 0.00 - - - - Magnitude - Magnitude - - - Available (GRC) Disponível (GRC) - Unconfirmed: Não confirmada: - Your current total balance O seu saldo total atual - Staking A realizar stake: - Blocks: Blocos: - Difficulty: Dificuldade: - Net Weight: Peso da Rede: - Researcher Investigador - Open the Manual Reward Claim (MRC) request page Abrir a página de pedido de Pedido de Recompensa Manual (MRC) - - Magnitude: - Magnitude: - - - Status: Estado: - You are approaching the accrual limit of 16384 GRC. If you have a relatively low balance, you should request payment via MRC so that you do not lose earned rewards. Está a atingir o limite de acumulação de 16384 GRC. Se tiver um saldo relativamente baixo, deve solicitar o pagamento através de MRC para que não perca as recompensas ganhas. - Recent Transactions Transações Recentes - Current Polls Sondagens Atuais - - Out of Sync Fora de Sincronia - - Pool - Pool - - - Staking Only A Realizar Stake Apenas @@ -2575,32 +1984,22 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PeerTableModel - Node ID ID do Nódulo - Node/Service Nódulo/Serviço - - Ping - Ping - - - Sent Enviado - Received Recebido - User Agent Agente do Utilizador @@ -2608,93 +2007,62 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollCard - Form Formulário - Votes: Votos: - Expiration: Data de Término: - Top Answer: Resposta Mais Votada: - Total Weight: Peso Total: - Poll Type Tipo de Sonadagem - - % of AVW: - %s do AVW - - - - AVW: - AVW: - - - Your Last Vote: O Seu Último Voto: - Your Vote Weight: O Peso do Seu Voto: - Your % of AVW: A Sua % de AVW - Balance Balanço - - Magnitude - Magnitude - - - Validated Validado - Invalid Inválido - - Voting finished. Votação terminada. - Vote Voto - Details Detalhes @@ -2702,7 +2070,6 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollCardView - Form Formulário @@ -2710,17 +2077,14 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollDetails - Form Formulário - Additional Fields Campos Adicionais - Top Answer: Resposta Mais Votada: @@ -2728,12 +2092,10 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollResultChoiceItem - Form Formulário - Weight: Peso: @@ -2741,12 +2103,10 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollResultDialog - Poll Details Detalhes da Sondagem - Poll ID ID da Sondagem @@ -2754,27 +2114,22 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollTab - Form Formulário - - Press "Refresh" to update the list. - Clique em "Recarregar " para atualizar a lista. + Press "Refresh" to update the list. + Clique em "Recarregar " para atualizar a lista. - This may take several minutes. Isto pode demorar alguns minutos. - Show Results Mostrar Resultados - Vote Voto @@ -2782,52 +2137,42 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollTableDataModel - Title Título - Poll Type Tipo de Sondagem - Duration Duração - Expiration Data de Término - Weight Type Tipo de Peso - Votes Votos - Total Weight Peso Total - % of Active Vote Weight % Peso dos Votos Ativos - Validated Validado - Top Answer Resposta Mais Votada @@ -2835,7 +2180,6 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollWizard - Create a Poll Criar uma Sondagem @@ -2843,108 +2187,86 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollWizardDetailsPage - Poll Details Detalhes da Sondagem - Some fields are locked for the selected poll type. Alguns campos estão bloqueados para o tipo de sondagem selecionada. - Poll Type: Tipo de Sondagem: - Duration: Duração: - days dias - Title: Título: - Question: Questão: - Discussion URL: URL de Discussão: - A link to the main discussion thread on GitHub or Reddit. Link para a discussão principal no GitHub ou no Reddit. - Weight Type: Tipo de Peso: - Response Type: Tipo de Resposta: - Choices: Escolhas: - A poll with a yes/no/abstain response type cannot include any additional custom choices. Uma sondagem com uma resposta do tipo sim/não/abster-se, não pode incluir quaisquer escolhas adicionais. - Additional Fields: Campos Adicionais: - - Create Poll Criar Sondagem - Balance Balanço - Magnitude+Balance Magnitude+Balanço - Yes/No/Abstain Sim/Não/Abster-se - Single Choice Escolha Única - Multiple Choice Escolha Múltipla - This poll will cost %1 plus a transaction fee. Continue? Esta sondagem irá custar %1 para além duma taxa adicional. Continuar? @@ -2952,42 +2274,34 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollWizardProjectPage - Project Listing Proposal Proposta da Listagem de Projetos - Add an unlisted project Adicionar um projeto não listado - Remove a listed project Remover um projeto listado - Proposals must follow community guidelines for validation. Please review the wiki and verify that the prerequisites have been fulfilled: As propostas devem seguir as diretrizes da comunidade, para que sejam validadas. Por favor reveja a wiki e verifique que os pré requisitos foram preenchidos: - Project Name: Nome do Projeto: - This project satisfies the Gridcoin listing criteria. Este projeto satisfaz a listagem de critérios do Gridcoin. - Project URL URL do Projeto - Choose a project to delist: Escolha um projeto para retirar: @@ -2995,17 +2309,14 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollWizardSummaryPage - Poll Created Sondagem Criada - The poll will activate with the next block. A sondagem será ativada no próximo bloco. - Copy ID Copiar ID @@ -3013,17 +2324,14 @@ Isto significa que uma taxa de pelo menos %2 é necessária. PollWizardTypePage - Create a Poll Criar uma Sondagem - The Gridcoin community established guidelines for polls with requirements for each type. Please read the wiki for more information: A comunidade Gridcoin estabeleceu diretrizes para as sondagem, com requisitos para cada tipo. Por favor leia a wiki para mais informações: - Choose a poll type: Escolha o tipo de sondagem: @@ -3031,45 +2339,29 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ProjectTableModel - Name Nome - Eligible Elegível - Whitelist Lista Aprovada - Has GDPR Controls Tem Controles GDPR - - Magnitude - Magnitude - - - Avg. Credit Média de Créditos - - - CPID - CPID - - + QObject - Error: Cannot parse command line arguments. Please check the arguments and ensure they are valid and formatted correctly: @@ -3077,129 +2369,84 @@ Isto significa que uma taxa de pelo menos %2 é necessária. - Error: Cannot read configuration file. Please check the path and format of the file. Erro: Não é possível ler o ficheiro de configuração. Verifique o caminho e o formato do ficheiro. - - Error: Specified data directory "%1" does not exist. + Error: Specified data directory "%1" does not exist. Erro: A diretoria %1 especificada não existe. - Error: Cannot obtain a lock on the specified data directory. An instance is probably already using that directory. Erro: Não foi possível cadear a diretoria de dados especificada. Uma instância já está provavelmente a utilizar essa diretoria - Error: Cannot parse configuration file: %1. Erro: Não foi possível analisar o ficheiro de configuração: %1. - Error initializing settings: %1 Erro ao inicializar as definições: %1 - - %1 didn't yet exit safely... + %1 didn't yet exit safely... %1 ainda não saiu de modo seguro... - N/A N/D - - - %1 ms - %1 ms - - - - - %1 s - %1 s - - %n second(s) - %n segundo(s)%n segundo(s)%n segundo(s) + + %n segundo(s) + %n segundo(s) + - %n minute(s) - %n minuto(s)%n minuto(s)%n minuto(s) + + %n minuto(s) + %n minuto(s) + - %n hour(s) - %n hora(s)%n hora(s)%n hora(s) + + %n hora(s) + %n hora(s) + - %n day(s) - %n dia(s)%n dia(s)%n dia(s) + + %n dia(s) + %n dia(s) + - - %n week(s) - %n semana(s)%n semana(s)%n semana(s) + + %n semana(s) + %n semana(s) + - %1 and %2 %1 e %2 - %n year(s) - %n ano(s)%n ano(s)%n ano(s) - - - - %1 B - %1 B - - - - %1 KB - %1 KB - - - - %1 MB - %1 MB - - - - %1 GB - %1 GB - - - - %1 d - %1 d - - - - %1 h - %1 h - - - - %1 m - %1 m + + %n ano(s) + %n ano(s) + - None Nenhum - %1 remaining. %1 restante. @@ -3207,57 +2454,46 @@ Isto significa que uma taxa de pelo menos %2 é necessária. QRCodeDialog - QR Code Dialog Diálogo de Código QR - Request Payment Solicitar Pagamento - Label: Etiqueta: - Message: Mensagem: - Amount: Quantia: - &Save As... &Guardar Como... - Error encoding URI into QR Code. Erro ao codificar URI para Código QR. - The entered amount is invalid, please check. A quantia introduzida é inválida, por favor verifique. - Resulting URI too long, try to reduce the text for label / message. Resultado do URI demasiado longo, tente reduzir o texto para a etiqueta / mensagem. - Save QR Code Guardar Código QR - PNG Image Name of PNG file format Imagem PNG @@ -3266,433 +2502,278 @@ Isto significa que uma taxa de pelo menos %2 é necessária. RPCConsole - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - N/A N/D - Client version Versão do cliente - &Information &Informação - Startup time Hora de Inicialização - Number of connections Número de ligações - Block chain Blockchain - Current number of blocks Número atual de blocos - Qt version Versão Qt - Difficulty Dificuldade - Last block time Data do último bloco - &Open &Abrir - &Clear &Limpar - - &Peers - &Peers - - - Banned peers Peers banidos - - Select a peer to view detailed information. Selecione um peer para visualizar a informação detalhada - Whitelisted Na Lista Aprovada - Direction Direção - Version Versão - User Agent Agente do Utilizador - Services Serviços - Starting Block Bloco Inicial - Synced Headers Cabeçalhos Sincronizados - Synced Blocks Blocos Sincronizados - Ban Score Resultado do Ban - Connection Time Tempo de Conexão - Last Send Último Enviado - Last Receive Último Recebido - Sent Enviado - Received Recebido - Ping Time Tempo de Ping - The duration of a currently outstanding ping. A duração de pings excecionais actuais. - Ping Wait Espera de Ping - Min Ping Ping Mínimo - Time Offset Diferença Tempo - &Console &Consola - - &Scraper - &Scraper - - - &Network Traffic &Tráfego de Rede - Totals Totais - In: Entrada: - Out: Saída: - Debug log file Ficheiro de registo de depuração - Clear console Limpar consola - Gridcoin - Debug Console Gridcoin - Consola de Depuração - Boost version Versão de Boost - Gridcoin Core: Núcleo Gridcoin: - Network: Rede: - On testnet Na rede de testes - Estimated total blocks Total estimado de blocos - Open the Gridcoin debug log file from the current data directory. This can take a few seconds for large log files. Abre o ficheiro de registo de depuração do Gridcoin na directoria atual. Isto pode levar alguns segundos para ficheiros de registo maiores. - Command-line options Opções da linha de comandos - Show the Gridcoin help message to get a list with possible Gridcoin command-line options. Mostra a mensagem de ajuda do Gridcoin para obter uma lista com possíveis opções da linha de comandos. - &Show &Mostrar - OpenSSL version Versão OpenSSL - Client name Nome do cliente - &Disconnect &Desligar - - - - Ban for Banir por - 1 &hour 1 &hora - 1 &day 1 &dia - 1 &week 1 &semana - 1 &year 1 &ano - &Unban &Desbloquear - Yes Sim - No Não - Welcome to the Gridcoin RPC console! Bem-vindo à consola RPC Gridcoin! - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Use as setas para cima e para baixo para navegar no histórico e, <b>Ctrl-L</b> para limpar o ecrã. - Type <b>help</b> for an overview of available commands. Escreva <b>help</b> para visualizar os comandos disponíveis. - - %1 B - %1 B - - - - %1 KB - %1 KB - - - - %1 MB - %1 MB - - - - %1 GB - %1 GB - - - - %1 m - %1 m - - - - %1 h - %1 h - - - - %1 h %2 m - %1 h %2 m - - - (node id: %1) (id do nó: %1) - - via %1 - via %1 - - - - never nunca - Inbound Entrada - Outbound Saída - - Unknown Desconhecido @@ -3700,13 +2781,10 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ReceiveCoinsPage - - Receive Payment Receber Pagamento - Search by address or label Pesquisar por endereço ou etiqueta @@ -3714,83 +2792,66 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherModel - Beacon is active. Beacon está ativo. - Balance too low to send a beacon contract. Balanço muito baixo para enviar um contrato de beacon. - Beacon private key missing or invalid. Chave privada do Beacon inválida ou perdida. - Current beacon is not renewable yet. Beacon atual não é possível de ser já renovado. - Unable to send beacon transaction. See debug.log Impossível enviar a transação do beacon. Ver debug.log - Unlock wallet fully to send a beacon transaction. Desbloquear completamente a carteira para enviar uma transação do beacon. - No active beacon. Sem beacon ativo. - No CPID detected. CPID não detetado. - Zero magnitude in the last superblock. Magnitude zero no último super bloco. - Pending beacon is awaiting network confirmation. Beacon pendente a aguardar confirmação da rede. - Beacon expires soon. Renew immediately. Beacon expira brevemente. Renove-o imediatamente. - Beacon eligible for renewal. Beacon elegível para renovação. - - Waiting for sync... Aguardando pela sincronização... - Not whitelisted Não listado na lista aprovada - Not attached Não anexado - Uses external adapter Utiliza adaptador externo @@ -3798,12 +2859,10 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizard - Researcher Configuration Configuração de Investigador - &Start Over &Recomeçar @@ -3811,82 +2870,70 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardAuthPage - - Beacon Verification Verificação do Beacon - Gridcoin needs to verify your BOINC account CPID. Please follow the instructions below to change your BOINC account username. The network needs 24 to 48 hours to verify a new CPID. Gridcoin necessita de verificar o CPID da sua conta BOINC. Por favor, siga as instruções abaixo para modificar o seu nome de utilizador do BOINC. A rede necessita de 24 a 48 horas para verificar um novo CPID. - 1. Sign in to your account at the website for a whitelisted BOINC project. 1. Entre na sua conta no sítio web dum projeto BOINC que esteja na lista aprovada. - - 2. Visit the settings page to change your username. Many projects label it as "other account info". - 2. Visite a página de configurações para alterar o nome de utilizador. Muitos projetos identificam como "outra informação da conta" + 2. Visit the settings page to change your username. Many projects label it as "other account info". + 2. Visite a página de configurações para alterar o nome de utilizador. Muitos projetos identificam como "outra informação da conta" - - 3. Change your "name" (real name or nickname) to the following verification code: - 3. Altere o seu "nome" (nome real ou alcunha) para o seguinte código de verificação: + 3. Change your "name" (real name or nickname) to the following verification code: + 3. Altere o seu "nome" (nome real ou alcunha) para o seguinte código de verificação: - Copy the verification code to the system clipboard Copie o código de verificação para a área de transferência - &Copy &Copiar - - 4. Some projects will not export your statistics by default. If available, enable the privacy setting that gives consent to the project to export your statistics data. Many projects place this setting on the "Preferences for this Project" page and label it as "Do you consent to exporting your data to BOINC statistics aggregation web sites?" - 4. Alguns projetos não irão exportar as suas estatísticas por defeito. Se a opção estiver disponível, deve alterar as definições de privacidade que consentem que um projeto possa exportar os dados das suas estatísticas. Muitos projetos colocam esta definição na página "Preferências para este Projeto" e etiquetam-na como "Pretende consentir a exportação dos seus dados para sítios web de estatísticas de agregação do BOINC ?" + 4. Some projects will not export your statistics by default. If available, enable the privacy setting that gives consent to the project to export your statistics data. Many projects place this setting on the "Preferences for this Project" page and label it as "Do you consent to exporting your data to BOINC statistics aggregation web sites?" + 4. Alguns projetos não irão exportar as suas estatísticas por defeito. Se a opção estiver disponível, deve alterar as definições de privacidade que consentem que um projeto possa exportar os dados das suas estatísticas. Muitos projetos colocam esta definição na página "Preferências para este Projeto" e etiquetam-na como "Pretende consentir a exportação dos seus dados para sítios web de estatísticas de agregação do BOINC ?" - - 5. Wait 24 to 48 hours for the verification process to finish (beacon status will change to "active"). - 5. Aguarde 24 a 48 horas para o processo de verificação terminar (o estado do beacon irá passar a "ativo") + 5. Wait 24 to 48 hours for the verification process to finish (beacon status will change to "active"). + 5. Aguarde 24 a 48 horas para o processo de verificação terminar (o estado do beacon irá passar a "ativo") - 6. After that, you may change the username back to your preference. 6. Depois disso, pode voltar a alterar o seu nome de utilizador de acordo com as suas preferências. - <html> <head/> <body> -<h4 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> -<span style=" font-size:medium; font-weight:600;">Remember:</span> +<h4 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> +<span style=" font-size:medium; font-weight:600;">Remember:</span> </h4> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 0;"> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The network only needs to verify the code above at a single whitelisted BOINC project even when you participate in multiple projects. </li> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The verification code expires after three days pass. </li> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A beacon expires after six months pass. </li><li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A beacon becomes eligible for renewal after five months pass. The wallet will remind you to renew the beacon. </li> -<li style=" margin-top:6px; margin-bottom:12px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You will not need to change your username again to renew a beacon unless it expires. </li> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 0;"> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The network only needs to verify the code above at a single whitelisted BOINC project even when you participate in multiple projects. </li> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The verification code expires after three days pass. </li> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A beacon expires after six months pass. </li><li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A beacon becomes eligible for renewal after five months pass. The wallet will remind you to renew the beacon. </li> +<li style=" margin-top:6px; margin-bottom:12px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You will not need to change your username again to renew a beacon unless it expires. </li> </ul> </body> </html> <html> <head/> <body> -<h4 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> -<span style=" font-size:medium; font-weight:600;">Lembre-se</span> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 0;"> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A rede apenas necessita que verifique o código acima num projeto BOINC que esteja na lista aprovada, mesmo que participe em múltiplos projetos. </li> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O código de verificação expira após 3 dias. </li> -<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O beacon expira após 6 meses</li><li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O beacon torna-se elegível para renovação após passarem 5 meses. A carteira irá relembrá-lo para renovar o beacon. </li> -<li style=" margin-top:6px; margin-bottom:12px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Não necessita de mudar o seu nome de utilizador novamente depois de renovar o beacon, a não ser que o deixe expirar. </li> +<h4 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> +<span style=" font-size:medium; font-weight:600;">Lembre-se</span> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 0;"> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A rede apenas necessita que verifique o código acima num projeto BOINC que esteja na lista aprovada, mesmo que participe em múltiplos projetos. </li> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O código de verificação expira após 3 dias. </li> +<li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O beacon expira após 6 meses</li><li style=" margin-top:6px; margin-bottom:0px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">O beacon torna-se elegível para renovação após passarem 5 meses. A carteira irá relembrá-lo para renovar o beacon. </li> +<li style=" margin-top:6px; margin-bottom:12px; margin-left:15px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Não necessita de mudar o seu nome de utilizador novamente depois de renovar o beacon, a não ser que o deixe expirar. </li> </ul> </body> </html> @@ -3895,47 +2942,37 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardBeaconPage - - Beacon Advertisement Anúncio do Beacon - A beacon links your BOINC accounts to your wallet. After sending a beacon, the network tracks your BOINC statistics to calculate research rewards. Um beacon linka a sua conta de BOINC à sua carteira. Depois de enviar o beacon, a rede monitoriza as suas estatísticas do BOINC para calcular as recompensas de investigação. - &Advertise Beacon &Anunciar Beacon - - Press "Next" to continue. - Carregue em "Seguinte" para continuar. + Press "Next" to continue. + Carregue em "Seguinte" para continuar. ResearcherWizardEmailPage - - BOINC Email Address Endereço de Email do BOINC - Enter the email address that you use for your BOINC project accounts. Gridcoin uses this email address to find BOINC projects on your computer. Insira o endereço de email que utiliza nos projetos do BOINC. O Gridcoin utiliza esse email para encontrar os projetos do BOINC no seu computador. - Email Address: Endereço de Email: - The wallet will never transmit your email address. A carteira nunca irá transmitir o seu endereço de email. @@ -3943,115 +2980,87 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardInvestorPage - Summary Sumário - Investor Mode Modo de Investidor - You opted out of research rewards and will earn staking rewards only. Optou por não receber recompensas de investigação, e irá ganhar apenas as recompensas de realizar stake apenas. - - Press "Start Over" if you want to switch modes. - Carregue em "Recomeçar" se quiser mudar de modo. + Press "Start Over" if you want to switch modes. + Carregue em "Recomeçar" se quiser mudar de modo. ResearcherWizardModeDetailPage - Select Researcher Mode Selecione Modo de Investigador - How can I participate? Como posso participar? - <html> <head/> <body> -<p>You can participate as either a miner or investor. <span style=" font-weight:600;">Miners</span> earn Gridcoin by participating in whitelisted BOINC projects. To redeem their rewards, miners must stake blocks. <span style=" font-weight:600;">Solo Miners</span> stake blocks on their own which typically requires a balance of at least 5000 GRC. <span style=" font-weight:600;">Pool Miners</span> avoid this upfront investment by letting a third party (the pool) stake blocks on their behalf. Pool mining is recommended for new users with a low initial balance. <span style=" font-weight:600;">Investors</span> own Gridcoin but do not participate in BOINC mining. By using their balance to stake blocks, investors help to secure the network and are rewarded 10 GRC per block.</p> +<p>You can participate as either a miner or investor. <span style=" font-weight:600;">Miners</span> earn Gridcoin by participating in whitelisted BOINC projects. To redeem their rewards, miners must stake blocks. <span style=" font-weight:600;">Solo Miners</span> stake blocks on their own which typically requires a balance of at least 5000 GRC. <span style=" font-weight:600;">Pool Miners</span> avoid this upfront investment by letting a third party (the pool) stake blocks on their behalf. Pool mining is recommended for new users with a low initial balance. <span style=" font-weight:600;">Investors</span> own Gridcoin but do not participate in BOINC mining. By using their balance to stake blocks, investors help to secure the network and are rewarded 10 GRC per block.</p> </body> </html> <html> <head/> <body> -<p>Pode participar como minerador ou investidor. <span style=" font-weight:600;">Mineradores</span> ganham Gridcoins ao participar em projectos BOINC na lista aprovada. Para ganharem as suas recompensar, os mineradores têm de realizar stake em blocos. <span style=" font-weight:600;">Mineradores a solo</span> realizam stake em blocos por sua conta, o que tipicamente requer um balanço inicial de pelo menos 5000 GRC. <span style=" font-weight:600;">Mineradores de Pool</span> evitam este investimento inicial ao deixar que uma terceira parte (a pool) realize o stake de blocos em seu nome. Mineração em Pool é recomendado para novos utilizadores que têm um balanço inicial baixo. <span style=" font-weight:600;">Investidores</span> têm o Gridcoin mas não participam na Mineração do BOINC. Ao utilizar o seu balanço para realizar stake de blocos, os investidor ajudam a garantir a segurança da rede e são recompensados com 10 GRC por bloco. </p> +<p>Pode participar como minerador ou investidor. <span style=" font-weight:600;">Mineradores</span> ganham Gridcoins ao participar em projectos BOINC na lista aprovada. Para ganharem as suas recompensar, os mineradores têm de realizar stake em blocos. <span style=" font-weight:600;">Mineradores a solo</span> realizam stake em blocos por sua conta, o que tipicamente requer um balanço inicial de pelo menos 5000 GRC. <span style=" font-weight:600;">Mineradores de Pool</span> evitam este investimento inicial ao deixar que uma terceira parte (a pool) realize o stake de blocos em seu nome. Mineração em Pool é recomendado para novos utilizadores que têm um balanço inicial baixo. <span style=" font-weight:600;">Investidores</span> têm o Gridcoin mas não participam na Mineração do BOINC. Ao utilizar o seu balanço para realizar stake de blocos, os investidor ajudam a garantir a segurança da rede e são recompensados com 10 GRC por bloco. </p> </body> </html> - Earn 10 GRC Block Reward Ganhe 10 GRC por recompensa por bloco - Ability to Vote Capacidade para Votar - Decentralized Descentralizada - Helps Secure Network Ajuda a Segurança da Rede - Keep 100% of Rewards Mantenha 100% das Recompensas - Earn BOINC Rewards Ganhe Recompensas do BOINC - No Upfront Investment Sem investimento Inicial - My Choice: Minha Escolha: - BOINC Leaderboards Tabelas de Classificação do BOINC - - Pool - Pool - - - - Solo - Solo - - - Investor Investidor - Pool Only Pool Apenas @@ -4059,32 +3068,18 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardModePage - Select Researcher Mode Selecione Modo de Investigador - How would you like to participate? Como gostaria de participar? - - Solo - Solo - - - - Pool - Pool - - - Investor Investidor - Help me choose... Ajude-me a escolher... @@ -4092,72 +3087,50 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardPoolPage - Summary Sumário - Pool Mode Modo de Mineração por Pool - - In this mode, a pool will take care of staking research rewards for you. Your wallet can still earn standard staking rewards on your balance. You do not need a BOINC account, CPID, or beacon. Please choose a pool and follow the instructions on the website to sign up and connect the pool's account manager to BOINC: + In this mode, a pool will take care of staking research rewards for you. Your wallet can still earn standard staking rewards on your balance. You do not need a BOINC account, CPID, or beacon. Please choose a pool and follow the instructions on the website to sign up and connect the pool's account manager to BOINC: Neste modo, a pool irá tomar conta de realizar o stake para pesquisar recompensas para si. A sua carteira pode ainda ganhar recompensas normais por realizar stake. Não precisa de uma conta BOINC, CPID ou Beacon. Por favor escolha uma pool e siga as instruções no sítio web para se registar e ligar a uma conta duma pool gestora do BOINC: - - grcpool - grcpool - - - - Arikado Pool - Arikado Pool - - - Website URL URL do Sítio Web - As you sign up, the pool may ask for a payment address to send earnings to. Press the button below to generate an address. Ao registar-se, a pool pode-lhe pedir um endereço para receber os pagamentos. Carregue no botão abaixo para gerar um endereço. - New &Address Novo &Enderenço - &Copy &Copiar - - Press "Next" when you are done. - Carregue em "Seguinte" quando estiver pronto. + Press "Next" when you are done. + Carregue em "Seguinte" quando estiver pronto. - Address Label Etiqueta do Endereço - Label: Etiqueta: - Pool Receiving Address Endereço de Receção da Pool - Error: failed to generate a new address. Erro: falhou ao gerar um novo endereço. @@ -4165,42 +3138,34 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardPoolSummaryPage - BOINC CPID Detection Deteção do CPID do BOINC - Pool Mode Modo de Mineração por Pool - BOINC Folder: Diretoria do BOINC: - Pool Status: Estado da Pool: - Re-scan the BOINC projects on your computer. Reexamine os projetos BOINC no seu computador. - &Refresh &Atualizar - Pool projects detected Projetos da pool detetados - No pool projects detected Sem projetos da Pool detetados @@ -4208,43 +3173,34 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardProjectsPage - - BOINC CPID Detection Deteção do CPID do BOINC - Gridcoin scans the BOINC projects on your computer to find an eligible cross-project identifier (CPID). The network tracks CPIDs to allocate research rewards. O Gridcoin procura os os projetos BOINC no seu computador para encontrar um identificador de cruzamento de projetos (CPID). A rede pesquisa esse CPID para distribuir as recompensas de investigação. - Email Address: Endereço de Email: - BOINC Folder: Diretoria do BOINC: - Selected CPID: CPID Selecionado: - Re-scan the BOINC projects on your computer. Reexaminar os projetos BOINC no seu computador. - &Refresh &Atualizar - An error occurred while saving the email address to the configuration file. Please see debug.log for details. Ocorreu um erro ao guardar o endereço de email para o ficheiro de configuração. Por favor veja o debug.log para detalhes. @@ -4252,123 +3208,90 @@ Isto significa que uma taxa de pelo menos %2 é necessária. ResearcherWizardSummaryPage - Researcher Summary Sumário de Investigação - S&ummary S&umário - - Everything looks good. Tudo parece bem. - Review Beacon Verification Rever Verificação do Beacon - Status: Estado: - - Magnitude: - Magnitude: - - - Pending Reward: Recompensas Pendentes: - - Beacon: - Beacon: - - - Age: Idade: - Expires: Expira: - Address: Endereço: - &Renew &Renovar - &Projects &Projetos - Email Address: Endereço de Email: - BOINC Folder: Diretoria do BOINC: - Selected CPID: CPID Selecionado: - Re-scan the BOINC projects on your computer. Reexaminar os projetos BOINC no seu computador. - &Refresh &Atualizar - Waiting for sync... Aguardando pela sincronização... - Beacon awaiting confirmation. Beacon a aguardar confirmação. - Beacon renewal available. Renovação do beacon disponível. - Split CPID or mismatched email. CPID dividido ou eMail não correspondente. - - Your projects either refer to more than one CPID or your projects' email do not match what you used to configure Gridcoin here. Please ensure all of your projects are attached using the same email address, the email address matches what was configured here, and if you added a project recently, update that project and then all other projects using the update button in the BOINC manager, then restart the client and recheck. + Your projects either refer to more than one CPID or your projects' email do not match what you used to configure Gridcoin here. Please ensure all of your projects are attached using the same email address, the email address matches what was configured here, and if you added a project recently, update that project and then all other projects using the update button in the BOINC manager, then restart the client and recheck. Os seus projetos referem-se a mais do que um CPID ou, o e-mail dos seus projetos não corresponde ao que utilizou para configurar o Gridcoin. Por favor, certifique-se de que todos os seus projetos estão anexados utilizando o mesmo endereço de e-mail, o que corresponde ao que foi configurado aqui, e se adicionou um projeto recentemente, atualize esse projeto de seguida, todos os outros projetos utilizando o botão de atualização no Gestor BOINC. Por último, reinicie o cliente e verifique novamente. - Waiting for magnitude. Aguardando pela magnitude @@ -4376,272 +3299,190 @@ Isto significa que uma taxa de pelo menos %2 é necessária. SendCoinsDialog - - - - - - - - Send Coins Enviar Moedas - Send Payment Enviar Pagamento - - 0.00 - 0.00 - - - - - Available (%1) Disponível (%1) - Coin Control Features (Advanced) Funcionalidades de Controlo de Moedas (Avançada) - - Inactive Inativo - Inputs... Entradas... - automatically selected selecionadas automaticamente - Insufficient funds! Fundos insuficientes! - Reset Repor - Consolidate Wizard Assistente de Consolidação - Quantity: Quantidade: - - - 0 - 0 - - - - Bytes: - Bytes: - - - Amount: Quantia: - - - - - 0.00 GRC - 0.00 GRC - - - Fee: Taxa: - Low Output: Produção Baixa: - no não - After Fee: Depois da taxa: - Change Modificar - custom change address alteração personalizada de endereço - Remove all transaction fields Remover todas os campos de transações - Send to multiple recipients at once Enviar para múltiplos destinatários de uma vez - Add &Recipient Adicionar &Destinatário - Clear &All Limpar &Tudo - Confirm the send action Confirme ação de envio - S&end E&nviar - Enter a Gridcoin address (e.g. S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) Insira um endereço Gridcoin (ex: S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) - Copy quantity Copiar quantidade - Copy amount Copiar quantia - Copy fee Copiar taxa - Copy after fee Copiar depois da taxa - Copy bytes Copiar bytes - Copy low output Copiar baixa produção - Copy change Copiar modificação - <b>%1</b> to %2 (%3) <b>%1</b> a %2 (%3) - Confirm send coins Confirme envio de moedas - Are you sure you want to send %1? Tem a certeza que quer enviar %1? - and e - The recipient address is not valid, please recheck. O endereço de destino não é válido, por favor verifique. - The amount to pay must be larger than 0. A quantia a pagar deverá ser maior que 0. - The amount exceeds your balance. A quantia excede o seu saldo. - The total exceeds your balance when the %1 transaction fee is included. O total excede o seu saldo quando a taxa de transação %1 está incluída. - Duplicate address found, can only send to each address once per send operation. Endereço duplicado encontrado, apenas poderá enviar uma vez por endereço, por cada operação de envio. - Error: Transaction creation failed. Erro: Criação da transação falhou. - Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. Erro: A transação foi rejeitada. Isso pode acontecer se algumas das suas moedas na carteira já tiverem sido gastas, se tiver utilizado uma cópia da wallet.dat e as moedas não tiverem sido marcadas como gastas aqui. - - (no label) (sem etiqueta) - WARNING: Invalid Gridcoin address AVISO: Endereço Gridcoin inválido - WARNING: unknown change address AVISO: endereço desconhecido - Active Ativo @@ -4649,73 +3490,50 @@ Isto significa que uma taxa de pelo menos %2 é necessária. SendCoinsEntry - A&mount: Q&antia: - Pay &To: Pagar &a: - Message: Mensagem: - &Label: &Etiqueta: - Form Formulário - The address to send the payment to (e.g. Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) O endereço para enviar o pagamento a (ex: Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) - - Alt+A - Alt+A - - - Paste address from clipboard Cole endereço da área de transferência - Send Custom Message to a Gridcoin Recipient Enviar Mensagem Personalizada a um Destinatário Gridcoin - Choose address from address book Escolha endereço do livro de endereços - - Alt+P - Alt+P - - - Remove this recipient Remover este destinatário - - Enter a label for this address to add it to your address book Escreva uma etiqueta a endereço para o adicionar ao seu livro de endereços - Enter a Gridcoin address (e.g. S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) Insira um endereço Gridcoin (ex: S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) @@ -4723,183 +3541,130 @@ Isto significa que uma taxa de pelo menos %2 é necessária. SignVerifyMessageDialog - Signatures - Sign / Verify a Message Assinaturas - Assinar / Verificar uma Mensagem - &Sign Message &Assinar Mensagem - You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. Pode assinar mensagens com os seus endereços para provar que são seus. Tenha atenção para não assinar mensagens vagas, pois ataques de phishing podem tentar enganá-lo, de modo a assinar a sua identidade para os atacantes. Assine apenas declarações completamente detalhadas com as quais concorde. - The address to sign the message with (e.g. Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) O endereço para assinar a mensagem com (ex: Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) - - Choose an address from the address book Escolha um endereço do livro de endereços - - - Alt+A - Alt+A - - - Paste address from clipboard Colar endereço da área de transferência - - Alt+P - Alt+P - - - Enter the message you want to sign here Escreva aqui a mensagem que deseja assinar - Copy the current signature to the system clipboard Copiar a assinatura atual para a área de transferência - Sign the message to prove you own this Gridcoin address Assinar a mensagem para provar que possui este endereço de Gridcoin - Sign &Message Assinar &Mensagem - Reset all sign message fields Repor todos os campos de assinatura da mensagem - - Clear &All Limpar &Tudo - - &Verify Message &Verificar Mensagem - Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Introduza o endereço de assinatura, mensagem (assegura que copia exatamente quebras de linha, espaços, tabuladores, etc.) e a assinatura abaixo para verificar a mensagem. Tenha atenção para não ler mais na assinatura do que o que estiver na mensagem assinada, para evitar ser enganado por um atacante que se encontre entre si e quem assinou a mensagem. - The address the message was signed with (e.g. Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) O endereço da mensagem foi assinado com (ex: Sjz75uKHzUQJnSdzvpiigEGxseKkDhQToX) - Verify the message to ensure it was signed with the specified Gridcoin address Verificar a mensagem para assegurar que foi assinada com o endereço Gridcoin especificado - Reset all verify message fields Repor todos os campos de verificação de mensagem - - Enter a Gridcoin address (e.g. S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) Insira um endereço Gridcoin (ex: S67nL4vELWwdDVzjgtEP4MxryarTZ9a8GB) - - Click "Sign Message" to generate signature - Clique "Assinar Mensagem" para gerar a assinatura + Click "Sign Message" to generate signature + Clique "Assinar Mensagem" para gerar a assinatura - Enter Gridcoin signature Insira assinatura do Gridcoin - - The entered address is invalid. O endereço introduzido é inválido. - - - - Please check the address and try again. Por favor verifique o endereço e tente de novo. - - The entered address does not refer to a key. O endereço introduzido não se refere a uma chave. - Wallet unlock was cancelled. O desbloqueio da carteira foi cancelado. - Private key for the entered address is not available. A chave privada para o endereço introduzido não está disponível. - Message signing failed. Assinatura de mensagem falhou. - Message signed. Mensagem assinada. - The signature could not be decoded. A assinatura não pode ser descodificada. - - Please check the signature and try again. Por favor, verifique a assinatura e tente novamente. - The signature did not match the message digest. A assinatura não condiz com o conteúdo da mensagem. - Message verification failed. Verificação da mensagem falhou. - Message verified. Mensagem verificada. @@ -4907,246 +3672,191 @@ Isto significa que uma taxa de pelo menos %2 é necessária. TransactionDesc - Open for %n more block(s) - Aberto para mais %n bloco(s)Aberto para mais %n bloco(s)Aberto por mais %n bloco(s) + + Aberto para mais %n bloco(s) + Aberto para mais %n bloco(s) + - Open until %1 Aberto até %1 - conflicted conflito - - %1/offline - %1/offline - - - %1/unconfirmed %1/não confirmada - %1 confirmations %1 confirmações - Status Estado - , has not been successfully broadcast yet , ainda não foi anunciada com sucesso - , broadcast through %n node(s) - , transmitida através de %n nó, transmitida através de %n nós, transmitida através de %n nó + + , transmitida através de %n nó + , transmitida através de %n nós + - Date Data - - Source Origem - Generated in CoinBase Gerada na CoinBase - Mined - PoS Minada - PoS - Mined - PoS+RR Minada - PoS+RR - Mined - Orphaned Minada - Orfã - PoS Side Stake Received PoS Side Stake Recebido - PoS+RR Side Stake Received PoS+RR Side Stake Recebido - PoS Side Stake Sent PoS Side Stake Enviado - PoS+RR Side Stake Sent PoS+RR Side Stake Enviado - MRC Payment Received Pagamento MRC Recebido - MRC Payment Sent Pagamento MRC Enviado - Mined - Superblock Minada - Super Bloco - Mined - Unknown Minada - Desconhecido - - From De - unknown desconhecido - - - To Para - - own address endereço próprio - label etiqueta - - - - - Credit Crédito - matures in %n more block(s) - matura em %n bloco(s)matura em %n bloco(s)matura em %n bloco(s) + + matura em %n bloco(s) + matura em %n bloco(s) + - not accepted não aceite - - - - Debit Débito - Transaction fee Taxa de transação - Net amount Valor líquido - - Message Mensagem - Comment Comentário - TX ID ID da TX - - Block Hash Hash do Bloco - Transaction Stake Data Dados de Stake da Transação - - Gridcoin generated coins must mature 110 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. - As moedas gerados pelo Gridcoin devem maturar durante 110 blocos antes de poderem ser gastas. Quando gerou este bloco, ele foi transmitido à rede para ser adicionado à blockchain. Se falhar a entrada na cadeia, o seu estado será alterado para "não aceite" e não será possível gastá-la. Isto pode acontecer ocasionalmente se outro nó gerar um bloco com segundos de diferença do seu. + Gridcoin generated coins must mature 110 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + As moedas gerados pelo Gridcoin devem maturar durante 110 blocos antes de poderem ser gastas. Quando gerou este bloco, ele foi transmitido à rede para ser adicionado à blockchain. Se falhar a entrada na cadeia, o seu estado será alterado para "não aceite" e não será possível gastá-la. Isto pode acontecer ocasionalmente se outro nó gerar um bloco com segundos de diferença do seu. - Transaction Debits/Credits Débitos/Créditos da Transação - Transaction Data Dados da Transação - Transaction Inputs Entradas de Transação - Amount Valor - true verdadeiro - false falso @@ -5154,17 +3864,14 @@ Isto significa que uma taxa de pelo menos %2 é necessária. TransactionDescDialog - Transaction details Detalhes da transação - This pane shows a detailed description of the transaction Esta janela mostra uma descrição detalhada da transação - C&lose F&echar @@ -5172,202 +3879,161 @@ Isto significa que uma taxa de pelo menos %2 é necessária. TransactionTableModel - Date Data - Type Tipo - Address Endereço - Amount Quantia - Open for %n more block(s) - Aberto por mais %n bloco(s)Aberto por mais %n bloco(s)Aberto por mais %n bloco(s) + + Aberto por mais %n bloco(s) + Aberto por mais %n bloco(s) + - Open until %1 Aberto até %1 - - Offline - Offline - - - Unconfirmed Não confirmado - Confirming (%1 of %2 recommended confirmations)<br> Confirmando (%1 de %2 confirmações recomendadas)<br> - Confirmed (%1 confirmations) Confirmada (%1 confirmações) - Conflicted Em Conflito - Immature (%1 confirmations, will be available after %2)<br> Imatura (%1 confirmações, estará disponível depois de %2)<br> - This block was not received by any other nodes<br> and will probably not be accepted! Este bloco não foi recebido por outros nós<br> e provavelmente não será aceite! - Generated but not accepted Gerado mas não aceite - Received with Recebido com - Received from Recebido de - Sent to Enviado para - Payment to yourself Pagamento ao próprio - Mined - PoS Minada - PoS - Mined - PoS+RR Minada - PoS+RR - Mined - Orphaned Minada - Orfã - PoS Side Stake Received PoS Side Stake Recebido - PoS+RR Side Stake Received PoS+RR Side Stake Recebido - PoS Side Stake Sent PoS Side Stake Enviado - PoS+RR Side Stake Sent PoS+RR Side Stake Enviado - MRC Payment Received Pagamento MRC Recebido - MRC Payment Sent Pagamento MRC Enviado - Mined - Superblock Minada - Super Bloco - Mined - Unknown Minada - Desconhecido - Beacon Advertisement Anúncio do Beacon - Poll Sondagem - Vote Voto - Manual Rewards Claim Request Solicitação Manual de Reivindicação de Recompensas - Message Mensagem - (n/a) (n/d) - Transaction status. Hover over this field to show number of confirmations. Estado da transação. Coloque ponteiro por cima deste campo para mostrar o número de confirmações. - Date and time that the transaction was received. Data e hora a que esta transação foi recebida. - Type of transaction. Tipo de transação. - Destination address of transaction. Endereço de destino da transação. - Amount removed from or added to balance. Quantia adicionada ou retirada do saldo. @@ -5375,178 +4041,139 @@ Isto significa que uma taxa de pelo menos %2 é necessária. TransactionView - Transaction History Histórico de Transações - Search by address or label Pesquisar por endereço ou etiqueta - All Time De Sempre - Today Hoje - This week Esta semana - This month Este mês - Last month Mês passado - This year Este ano - Range... Alcance... - All Types Todos os Tipos - Received with Recebida com - Sent to Enviada para - To yourself Para si - Mined Mineradas - Other Outro - Min amount Quantia mínima - Copy address Copiar endereço - Copy label Copiar etiqueta - Copy amount Copiar quantia - Copy transaction ID Copiar ID da transação - Edit label Editar etiqueta - Show transaction details Mostrar detalhes da transação - Export Transaction Data Exportar Dados da Transação - Comma separated file Name of CSV file format Ficheiro separado por vírgulas - Confirmed Confirmado - Date Data - Type Tipo - Label Etiqueta - Address Endereço - Amount Quantia - - ID - ID - - - Error exporting Erro ao exportar - Could not write to file %1. Não foi possível escrever para o ficheiro %1. - Range: Alcance: - to para @@ -5554,17 +4181,14 @@ Isto significa que uma taxa de pelo menos %2 é necessária. UpgradeQt - E&xit S&air - Quit application Sair da aplicação - &File &Ficheiro @@ -5572,7 +4196,6 @@ Isto significa que uma taxa de pelo menos %2 é necessária. VoteWizard - Vote Voto @@ -5580,7 +4203,6 @@ Isto significa que uma taxa de pelo menos %2 é necessária. VoteWizardBallotPage - Submit Vote Submeter Voto @@ -5588,17 +4210,14 @@ Isto significa que uma taxa de pelo menos %2 é necessária. VoteWizardSummaryPage - Vote Submitted Voto Submetido - Your vote will tally with the next block. O seu voto coincidirá com o próximo bloco. - Copy ID Copiar ID @@ -5606,18 +4225,14 @@ Isto significa que uma taxa de pelo menos %2 é necessária. VotingModel - - Please unlock the wallet. Por favor desbloqueie a carteira. - Poll not found. Sondagem não encontrada. - Failed to load poll from disk Falhou o carregamento das sondagens do disco @@ -5625,68 +4240,46 @@ Isto significa que uma taxa de pelo menos %2 é necessária. VotingPage - Voting A Votar - Polls Sondagem - Search by title Pesquisar por título - View as list. Ver como lista. - - - Alt+T - Alt+T - - - View as table. Ver como tabela. - Sort by... Ordenar por... - - Alt+S - Alt+S - - - &Refresh &Atualizar - Create &Poll Criar &Sondagem - - A new poll is available. Press "Refresh" to load it. - Uma nova sondagem está disponível. Carregue em "Atualizar" para a mostrar. + A new poll is available. Press "Refresh" to load it. + Uma nova sondagem está disponível. Carregue em "Atualizar" para a mostrar. - &Active &Ativo - &Completed &Concluído @@ -5694,7 +4287,6 @@ Isto significa que uma taxa de pelo menos %2 é necessária. WalletModel - Sending... Enviando... @@ -5702,1042 +4294,798 @@ Isto significa que uma taxa de pelo menos %2 é necessária. bitcoin-core - An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s Ocorreu um erro ao definir a porta %u do serviço RPC ao escutar em IPv6, a reverter para IPv4: %s - An error occurred while setting up the RPC port %u for listening on IPv4: %s Ocorreu um erro ao definir a porta %u do serviço RPC ao escutar em IPv4: %s - Usage: Utilização: - List commands Listar comandos - A poll with a yes/no/abstain response type cannot include any additional custom choices. Uma sondagem com uma resposta do tipo sim/não/abster-se, não pode incluir quaisquer escolhas adicionais. - Cannot obtain a lock on data directory %s. %s is probably already running and using that directory. Não foi possível cadear a diretoria de dados %s. %s já está provavelmente a utilizar essa diretoria. - Cannot obtain a lock on data directory %s. %s is probably already running. Não foi possivel cadear a diretoria de dados %s. %s já está provavelmente em execução. - Check that BOINC is installed and that you have the correct path in the config file if you installed it to a nonstandard location. Verifique que o BOINC está instalado e que tem o caminho correto no ficheiro de configuração, caso o tenha instalado numa localização não definida por padrão. - Error: Clock skew is 5 minutes or greater. Please check your clock settings. Erro: O sincronização do relógio é de 5 minutos ou mais. Verifique as definições do seu relógio. - Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. Erro: A transação foi rejeitada. Isso pode acontecer se algumas das na sua moedas na carteira já tiverem sido gastas, se tiver utilizado uma cópia da wallet.dat e as moedas não tiverem sido marcadas como gastas aqui. - Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds Erro: Esta transação devido à sua quantia, complexidade ou utilização de fundos recebidos recentemente, necessita de uma taxa de transação de pelo menos %s - For initiatives related to the Gridcoin community not covered by other poll types. Para iniciativas relacionadas com a Comunidade Gridcoin, não abrangidas por outros tipos de sondagem. - For polls about community representation, public relations, and communications. Para sondagens sobre representação comunitária, relações públicas e comunicações. - Please check your network and also check the config file and ensure your addnode entries are up-to-date. If you recently started the wallet, you may want to wait another few minutes for connections to build up and test again. Please see https://gridcoin.us/wiki/config-file.html and https://addnodes.cycy.me/. Por favor, verifique a sua rede e também o ficheiro de configuração e certifique-se de que as suas entradas addnode estão atualizadas. Se iniciou recentemente a carteira, poderá querer aguardar mais alguns minutos para que as ligações sejam estabelecidas e testar novamente. Consulte https://gridcoin.us/wiki/config-file.html e https://addnodes.cycy.me/. - Please ensure that you have followed the process to advertise and verify your beacon. You can use the research wizard (the beacon button on the overview screen). Certifique-se de que seguiu o processo para publicitar e verificar o seu beacon. Pode utilizar o assistente de pesquisa (o botão beacon no ecrã de resumo). - - Poll additional field value "%s" for field name "%s" exceeds %s characters. - A sondagem do valor de campo adicional "%s" para o nome de campo "%s" excede os %s caracteres. + Poll additional field value "%s" for field name "%s" exceeds %s characters. + A sondagem do valor de campo adicional "%s" para o nome de campo "%s" excede os %s caracteres. - Proposals related to Gridcoin management like poll requirements and funding. Propostas relacionadas com a gestão do Gridcoin, como requisitos de sondagem e financiamento. - Propose additions or removals of computing projects for research reward eligibility. Propor adições ou remoções de projetos de computação para a elegibilidade de prémios de investigação. - The IP for the port test site is unable to be resolved. This could mean your DNS is not working correctly. The wallet may operate without DNS, but it could be severely degraded, especially if the wallet is new and a database of prior successful connections has not been built up. Please check your computer and ensure name resolution is operating correctly. Não é possível resolver o IP do site de teste de portas. Isto pode significar que o seu DNS não está a funcionar corretamente. A carteira pode funcionar sem DNS, mas pode ser gravemente degradada, especialmente se a carteira for nova e não tiver sido criada uma base de dados de ligações anteriores bem sucedidas. Verifique o seu computador e certifique-se de que a resolução de nomes está a funcionar corretamente. - The connection to the port test site was refused. This could be a transient problem with the port test site, but could also be an issue with your firewall. If you are also failing the connection test, your firewall is most likely blocking network communications from the Gridcoin client. A ligação ao site de teste de portas foi recusada. Isto pode ser um problema transitório com o site de teste de portas, mas também pode ser um problema com a sua firewall. Se também estiver a falhar o teste de ligação, a sua firewall está provavelmente a bloquear as comunicações de rede do cliente Gridcoin. - The network has experienced a low-level error and this probably means your IP address or other network connection parameters are not configured correctly. Please check your network configuration on your computer. A rede sofreu um erro de baixo nível, o que provavelmente significa que o seu endereço IP ou outros parâmetros de ligação à rede não estão corretamente configurados. Verifique a configuração da rede no seu computador. - - The network is reporting an unspecified socket error. If you also are failing the connection test, then please check your computer's network configuration. + The network is reporting an unspecified socket error. If you also are failing the connection test, then please check your computer's network configuration. A rede está a reportar um erro de socket não especificado. Se também falhar o teste de ligação, verifique a configuração de rede do seu computador. - The port test site is closed on port. This could be a transient problem with the port test site, but could also be an issue with your firewall. If you are also failing the connection test, your firewall is most likely blocking network communications from the Gridcoin client. O sítio de teste de portas está fechado na porta. Isto pode ser um problema transitório com o site de teste de portas, mas também pode ser um problema com a sua firewall. Se também estiver a falhar o teste de ligação, a sua firewall está muito provavelmente a bloquear as comunicações de rede do cliente Gridcoin. - The wallet has less than five connections to the network and is unable to connect to an NTP server to check your computer clock. This is not necessarily a problem. You can wait a few minutes and try the test again. A carteira tem menos de cinco ligações à rede e não consegue ligar-se a um servidor NTP para verificar o relógio do seu computador. Isto não é necessariamente um problema. Pode esperar alguns minutos e repetir o teste novamente. - The wallet will now shutdown. Please start your wallet to begin sync from zero A carteira irá encerrar. Por favor, inicie a sua carteira para começar a sincronização do zero - There is a new leisure version available and you should upgrade as soon as practical. Existe uma nova versão de lazer disponível e deve ser atualizada assim que possível. - There is a new mandatory version available and you should upgrade as soon as possible to ensure your wallet remains in consensus with the network. Existe uma nova versão obrigatória disponível e deve atualizá-la o mais rapidamente possível para garantir que a sua carteira se mantém em consenso com a rede. - Verify (1) that you have BOINC installed correctly, (2) that you have attached at least one whitelisted project, (3) that you advertised your beacon with the same email as you use for your BOINC project(s), and (4) that the CPID on the overview screen matches the CPID when you login to your BOINC project(s) online. Verifique (1) se o BOINC está instalado corretamente, (2) se adicionou pelo menos um projeto da whitelist, (3) se anunciou seu beacon com o mesmo e-mail que usa para o(s) seu(s) projeto(s) BOINC e (4) se o CPID no ecrã de visão geral corresponde ao CPID quando inicia sessão no(s) seu(s) projeto(s) BOINC on-line. - Verify that you have actually completed workunits for the projects you have attached and that you have authorized the export of statistics. Please see https://gridcoin.us/guides/whitelist.htm. Verifique se as unidades de trabalho dos projetos que adicionou foram efetivamente concluídas e se autorizou a exportação de estatísticas. Consultar https://gridcoin.us/guides/whitelist.htm. - WARNING: A mandatory release is available. Please upgrade as soon as possible. AVISO: Uma versão obrigatória do cliente Gridcoin está disponível. Por favor atualize o mais rapidamente possível. - Warning: Clock skew is between 3 and 5 minutes. Please check your clock settings. Aviso: O desvio do relógio situa-se entre 3 e 5 minutos. Verifique as definições do seu relógio. - Warning: ETTS is > 90 days. It will take a very long time to receive your research rewards by staking - increase balance or use MRC Aviso: O ETTS é > 90 dias. Vai demorar muito tempo a receber as suas recompensas de investigação por staking - aumente o saldo ou utilize o MRC - Warning: ETTS is infinite. No coins to stake - increase balance or use MRC Aviso: O ETTS é infinito. Não há moedas para realizar stake - aumente o saldo ou use o MRC - Warning: Ending this process after Stage 2 will result in syncing from 0 or an incomplete/corrupted blockchain. - Aviso: Acabar este processo antes da Fase 2 irá resultar numa sincronização do "0", ou numa cadeia de blocos incompleta/corrupta. + Aviso: Acabar este processo antes da Fase 2 irá resultar numa sincronização do "0", ou numa cadeia de blocos incompleta/corrupta. - You have no balance and will be unable to retrieve your research rewards when solo crunching by staking. You can use MRC to retrieve your rewards, or you should acquire GRC to stake so you can retrieve your research rewards. Please see https://gridcoin.us/guides/boinc-install.htm. Não tens saldo e não será possível recuperar as tuas recompensas de investigação quando estiveres a fazer crunch a solo por staking. Podes usar MRC para recuperar as tuas recompensas, ou deverás adquirir GRC para fazer stake e poderes recuperar as tuas recompensas de investigação. Consulte https://gridcoin.us/guides/boinc-install.htm. - You will not be able to stake because you have less than %1 connection(s). Please check your network and also check the config file and ensure your addnode entries are up-to-date. If you recently started the wallet, you may want to wait another few minutes for connections to build up and then test again. Please see https://gridcoin.us/wiki/config-file.html and https://addnodes.cycy.me/. Não será possível realizar stake porque tem menos de %1 ligação(ões). Por favor, verifique a sua rede e verifique também o ficheiro de configuração e certifique-se de que as suas entradas addnode estão atualizadas. Se iniciou recentemente a carteira, pode querer esperar mais alguns minutos para que as ligações se estabeleçam e depois testar novamente. Consulte https://gridcoin.us/wiki/config-file.html e https://addnodes.cycy.me/. - Your balance is low given the current network difficulty to stake in a reasonable period of time to retrieve your research rewards when solo crunching. You should consider acquiring more GRC to stake more often, or else use MRC to retrieve your rewards. O seu saldo é baixo dada a dificuldade atual da rede em realizar stake num período de tempo razoável para recuperar as suas recompensas de investigação quando faz crunch a solo. Deve considerar a aquisição de mais GRC para realizar stake mais vezes, ou então usar MRC para recuperar as suas recompensas. - Your balance is too low given the current network difficulty to stake in a reasonable period of time to retrieve your research rewards when solo crunching. You can use MRC to retrieve your rewards, or you should acquire more GRC to stake more often. O teu saldo é demasiado baixo tendo em conta a dificuldade atual da rede, para poderes realizar stake num período de tempo razoável para recuperares as tuas recompensas de investigação quando fazes crunch a solo. Podes usar MRC para recuperar as tuas recompensas, ou deverás adquirir mais GRC para realizar stake mais vezes. - Your clock in your computer is significantly off from UTC or network time and this may seriously degrade the operation of the wallet, including maintaining connection to the network. You should check your time and time zone settings for your computer. A very common problem is the off by one hour caused by a time zone issue or problems with daylight savings time. O relógio do seu computador está significativamente desfasado da hora UTC ou da hora da rede, o que pode degradar seriamente o funcionamento da carteira, incluindo a manutenção da ligação à rede. Deve verificar as definições da hora e do fuso horário do seu computador. Um problema muito comum é o desfasamento de uma hora causado por um problema de fuso horário ou por problemas com a hora de Verão. - Your difficulty is extremely low and your wallet is almost certainly forked. Please ensure you are running the latest version and try removing the blockchain database and resyncing from genesis using the menu option. (Note this will take 2-4 hours.) A sua dificuldade é extremamente baixa e a sua carteira está quase de certeza bifurcada. Por favor, certifique-se de que está a correr a versão mais recente e tente remover a base de dados da cadeia de blocos e voltar a sincronizar a partir do génese usando a opção de menu. (Note que isso levará de 2-4 horas). - Your difficulty is low but your wallet is still in initial sync. Please recheck it later to see if this passes. A sua dificuldade é baixa, mas a sua carteira ainda está na sincronização inicial. Volte a verificar mais tarde para ver se isto ficou resolvido. - Your difficulty is very low and your wallet is probably forked. Please ensure you are running the latest version and try removing the blockchain database and resyncing from genesis using the menu option. (Note this will take 2-4 hours.) A sua dificuldade é muito baixa e a sua carteira está provavelmente bifurcada. Por favor, certifique-se de que está a correr a versão mais recente e tente remover a base de dados da cadeia de blocos e volte a sincronizar a partir da génese usando a opção de menu. (Observe que isso levará de 2-4 horas). - Your outbound connection count is critically low. Please check your the config file and ensure your addnode entries are up-to-date. If you recently started the wallet, you may want to wait another few minutes for connections to build up and then test again. Please see https://gridcoin.us/wiki/config-file.html and https://addnodes.cycy.me/. A sua contagem de ligações de saída é criticamente baixa. Por favor, verifique o seu ficheiro de configuração e certifique-se de que as suas entradas addnode estão atualizadas. Se iniciou recentemente a carteira, pode ter de esperar mais alguns minutos para que as ligações se estabeleçam e depois testar novamente. Consulte https://gridcoin.us/wiki/config-file.html e https://addnodes.cycy.me/. - Your outbound connection count is low. Please check your the config file and ensure your addnode entries are up-to-date. If you recently started the wallet, you may want to wait another few minutes for connections to build up and then test again. Please see https://gridcoin.us/wiki/config-file.html and https://addnodes.cycy.me/. A sua contagem de ligações de saída é baixa. Por favor, verifique o seu ficheiro de configuração e certifique-se de que as suas entradas addnode estão atualizadas. Se iniciou recentemente a carteira, pode ter de esperar mais alguns minutos para que as ligações se estabeleçam e depois testar novamente. Consulte https://gridcoin.us/wiki/config-file.html e https://addnodes.cycy.me/. - Your wallet is not in sync and has not previously been in sync during this run, please wait for the wallet to sync and retest. If there are other failures preventing the wallet from syncing, please correct those items and retest to see if this test passes. A sua carteira não está sincronizada e não esteve anteriormente sincronizada durante esta execução, aguarde que a carteira sincronize e volte a testar. Se existirem outras falhas que impeçam a sincronização da carteira, corrija esses itens e volte a testar para ver se este teste é concluído com sucesso. - Your wallet is out of sync with the network but was in sync before. If this fails there is likely a severe problem that is preventing the wallet from syncing. If the lack of sync is due to network connection issues, you will see failures on the network connection test(s). If the network connections pass, but your wallet fails this test, and continues to fail this test on repeated attempts with a few minutes in between, this could indicate a more serious issue. In that case you should check the debug log to see if it sheds light on the cause for no sync. A sua carteira está fora de sincronia com a rede, mas estava sincronizada anteriormente. Se isto falhar, é provável que exista um problema grave que esteja a impedir a sincronização da carteira. Se a falta de sincronização se dever a problemas de ligação à rede, verá falhas no(s) teste(s) de ligação à rede. Se as ligações de rede passarem, mas a sua carteira falhar este teste, e continuar a falhar este teste em tentativas repetidas com alguns minutos de intervalo, isto pode indicar um problema mais sério. Nesse caso, deve verificar o registo de depuração para ver se este esclarece a causa da falha na sincronização. - Your wallet is still in initial sync. If this is a sync from the beginning (genesis), the sync process can take from 2 to 4 hours, or longer on a slow computer. If you have synced your wallet before but you just started the wallet up, then wait a few more minutes and retry the diagnostics again. A sua carteira ainda está na sincronização inicial. Se se tratar de uma sincronização desde o início (génese), o processo de sincronização pode demorar de 2 a 4 horas, ou mais num computador lento. Se já sincronizou a sua carteira antes, mas acabou de a iniciar, aguarde mais alguns minutos e tente executar novamente o diagnóstico. - A poll choice cannot be empty. A escolha duma sondagem não pode estar vazia. - Are you sure you want to cancel the snapshot operation? Tem a certeza que quer cancelar a operação de snapshot? - Balance too low to create a contract. Balanço demasiado baixo para criar um contrato. - CPID Count Contagem CPID - CPID count polls are not supported. Contagem de sondagens CPID não são suportadas. - Cancel snapshot operation? Cancelar operação de snapshot? - Cancel Cancelar - - Cannot write to data directory '%s'; check permissions. - Não foi possível escrever na diretoria de dados '%s', verifique permissões. + Cannot write to data directory '%s'; check permissions. + Não foi possível escrever na diretoria de dados '%s', verifique permissões. - - Click "Show Details" to view changes in latest update. - Clique em "Mostrar Detalhes" para ver as alterações da ultima atualização. + Click "Show Details" to view changes in latest update. + Clique em "Mostrar Detalhes" para ver as alterações da ultima atualização. - Community Comunidade - Could not create transaction. See debug.log. Não foi possível criar transação. Ver debug.log - Duplicate poll additional field: %s Duplicar campo adicional na sondagem: %s - Duplicate poll choice: %s Duplicar escolhas da sondagem: %s - Duplicate response for poll choice: %s Duplicar respostas para escolha da sondagem %s - Entire balance reserved Saldo inteiro reservado - Error loading %s: Wallet corrupted Erro a carregar %s: Carteira corrompida - Error: Transaction creation failed. Erro: Criação de transação falhou. - Exceeded the number of choices in the poll: %s Excedidos número de escolhas na sondagem: %s - Failed to download snapshot.zip; See debug.log Falhou a transferência do snapshot.zip; Ver debug.log - Failed to rename bootstrap file to .old for backup purposes. Falhou a alteração de nome por motivos de backups no ficheiro bootstrap para .old. - Failed: 80 block difficulty is less than Falhou: a dificuldade de 80 blocos é menor que - Failed: Count = Falhou: Contagem = - Fees Collected Taxas coletadas - Files: Ficheiros: - For opinion or casual polls without any particular requirements. Para opiniões ou sondagens casuais sem requisitos especiais. - - GB) - GB) - - - - GB/ - GB/ - - - Get help for a command Obter ajuda para um comando - Governance Governança - Gridcoin Update Available Atualização do Gridcoin Disponível - - Gridcoin - Gridcoin - - - Initializing beacon registry from stored history... Inicializando registo de beacons do histórico armazenado... - Initializing local researcher context... Inicializando contexto de investigador local... - Initializing research reward accounting... Inicializando contagem de recompensas de investigação... - Insufficient funds. Fundos insuficientes. - - KB/s - KB/s - - - Loading beacon history... Carregando histórico de beacons... - Loading superblock cache... Carregando cache do super bloco... - Local version: Versão local: - - MB/s - MB/s - - - Magnitude+Balance Magnitude+Balanço - Magnitude-only polls are not supported. Sondagens de Magnitude apenas não são suportadas. - - Marketing - Marketing - - - Multiple Choice Escolha Múltipla - N/A N/D - No UTXOs available due to reserve balance Sem UTXOs disponíveis devido ao balanço de reserva - No address contains %s GRC in %s UTXOs or fewer. Sem endereços contendo %s GRC em %s UTXOs ou menos. - No coins Sem moedas - No eligible outputs greater than 1 GRC. Sem saídas elegíveis maiores que 1 GRC. - No mature coins Sem moedas maduras - No wallet available. Carteira não disponível. - Outbound communication to TCP port %1 appears to be blocked. Comunicação de saída na porta TCP %1 parece estar bloqueada. - Outbound communication to TCP port Comunicação de saída na porta TCP - Outreach Divulgação - Participant Count Contagem de Participantes - Participant count polls are not supported. Contagens de participantes das sondagens não são suportadas. - Passed: 80 block difficulty is Sucesso: A dificuldade de 80 blocos é - Passed: Count = Sucesso: Contagem = - Passed: ETTS = Sucesso: ETTS = - Please enter a poll discussion website URL. Por favor insira o URL do sítio web para a discussão da sondagem. - Please enter a poll title. Por favor insira o titulo da sondagem. - Please enter at least one response. Por favor insira pelo menos uma resposta. - Please enter at least two poll choices. Por favor insira pelo menos duas escolhas na sondagem. - - Poll additional field name "%s" exceeds %s characters. - O nome do campo adicional da sondagem "%s" excede os %s caracteres. + Poll additional field name "%s" exceeds %s characters. + O nome do campo adicional da sondagem "%s" excede os %s caracteres. - Poll cannot contain more than %s additional fields A sondagem não pode conter mais de %s campos adicionais - Poll cannot contain more than %s choices. A sondagem não pode conter mais do que %s escolhas. - - Poll choice "%s" exceeds %s characters. + Poll choice "%s" exceeds %s characters. Escolha %s da sondagem excede os %s carateres. - Poll discussion URL cannot exceed %s characters. URL de discussão da sondagem não pode exceder os %s carateres. - Poll duration cannot exceed %s days. Duração da sondagem não pode exceder os %s dias. - Poll duration must be at least %s days. Duração da sondagem tem de durar pelo menos %s dias. - Poll has already finished. A sondagem já terminou. - Poll only allows a single choice. A sondagem permite apenas uma escolha única. - Poll question cannot exceed %s characters. Questão da sondagem não pode exceder %s carateres. - Poll signature failed. See debug.log. Assinatura da sondagem falhou. Ver debug.log - Poll title cannot exceed %s characters. Título da sondagem não pode exceder %s carateres. - Poll with that title already exists. Please choose another title. Já existe uma sondagem com esse título. Por favor, escolha outro título. - - Pool - Pool - - - Project Listing Listagem de Projetos - Propose a change to Gridcoin at the protocol level. Propor uma alteração ao Gridcon ao nível do protocolo. - Propose marketing initiatives like ad campaigns. Propor iniciativas de marketing como campanhas publicitárias. - Protocol Development Protocolo de Desenvolvimento - Quorum Hash Quórum de Hashes - Reindexing blockchain from on disk block data files... Reindexando cadeia de blocos dos ficheiros de dados de blocos no disco... - Replaying contracts... Recarregando contratos.. - Reset Blockchain Data: Blockchain data removal failed. Repor os Dados da Cadeia de Blocos: Remoção de dados da cadeia de blocos falhou. - Reset Blockchain Data: Blockchain data removal was a success Repor os Dados da Cadeia de Blocos: Remoção de dados da cadeia de blocos realizada com sucesso - Send command to -server or gridcoinresearchd Enviar comando para -server ou gridcoinresearchd - Snapshot extraction failed! Cleaning up any extracted data Extração do Snapshot falhou! Limpando dados já extraídos - Snapshot operation canceled due to an invalid snapshot zip. Operação de snapshot cancelada devido a um snapshot.zip inválido. - Snapshot operation canceled. Operação de snapshot cancelada. - Snapshot operation successful! Operação de snapshot concluída com sucesso! - Stage (1/4): Downloading snapshot.zip: Speed Etapta (1/4): Transferindo o snapshot.zip: Velocidade - Stage (2/4): Verify SHA256SUM of snapshot.zip Etapa (2/4): Verificando SHA256SUM do snapshot.zip - Stage (3/4): Cleanup blockchain data Etapa (3/4): Limpando dados da cadeia de blocos - Stage (4/4): Extracting snapshot.zip Etapa (4/4): Extraindo o snapshot.zip - Survey Questionário - The field is not well-formed. O campo não está bem formado. - The field list is not well-formed. A lista do campo não está bem formada. - The wallet is now shutting down. Please restart your wallet. A carteira está a encerrar. Por favor reinicie a sua carteira. - The wallet will now shutdown. A carteira irá agora encerrar. - This wallet is almost certainly forked. A carteira está quase de certeza bifurcada. - This wallet is probably forked. A carteira está provavelmente bifurcada. - - Unable to create the PID file '%s': %s - Não foi possível criar o ficheiro PID "%s': %s + Unable to create the PID file '%s': %s + Não foi possível criar o ficheiro PID "%s': %s - Unknown poll type. This should never happen. Tipo de sondagem desconhecida. Isto nunca deverá acontecer. - Warning: 45 days < ETTS = Aviso: 45 dias < ETTS = - Warning: 80 block difficulty is less than Aviso: A dificuldade de 80 blocos é menor que - Warning: Cannot connect to NTP server Aviso: Não foi possível ligar ao servidor NTP - Warning: Count = Aviso: Contagem = - Wrong Payload version specified for current block height. Versão de carga útil incorreta especificada para a altura do bloco atual. - Yes/No/Abstain Sim/Não/Abster-se - You should check your time and time zone settings for your computer. Deve verificar as definições de hora e fuso horário do seu computador. - You will need to delete the following. Irá necessitar de eliminar o seguinte. - - "%s" is not a valid poll choice. - "%s" não é uma escolha válida da sondagem. + "%s" is not a valid poll choice. + "%s" não é uma escolha válida da sondagem. - appears to be blocked. parece estar bloqueado. - leisure opcional - mandatory obrigatória - unknown desconhecido - Balance Balanço - The %s developers Os %s desenvolvedores - - Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. + Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Erro: Argumento não suportado -socks encontrado. Definir a versão SOCKS não é mais possível, são apenas suportadas proxies SOCKS5. - Block Version Versão do Bloco - Block file load progress Progresso do carregamento do ficheiro de blocos - Block not in index Bloco em falha no index - Block read failed Bloco lido falhou - Blocks Loaded Blocos Carregados - Blocks Verified Blocos Verificados - Boinc Reward Recompensa do BOINC - - CPID - CPID - - - Client Version Versão do Cliente - Datadir: Diretório de dados: - Difficulty Dificuldade - Directories: Diretorias: - Disabled by configuration Desabilitado por configuração - ERROR ERRO - Eligible for Research Rewards Elegível para Pesquisar Recompensas - Error: Wallet locked, unable to create transaction. Erro: Carteira bloqueada, não foi possível criar transação - GitHub version: Versão GitHub: - Height Tamanho - Importing blockchain data file(s). Importando ficheiro(s) de dados da cadeia de blocos. - Interest Interesse - - Invalid amount for -peertimeout=<amount>: '%s' - Quantia inválida para -peertimeout=<amount>: '%s' + Invalid amount for -peertimeout=<amount>: '%s' + Quantia inválida para -peertimeout=<amount>: '%s' - Invalid team Equipa inválida - Is Superblock É um Super Bloco - Latest Version GitHub data response: Versão mais recente da resposta de dados do GitHub: - Loading Network Averages... Carregando Médias de Rede... - Loading banlist... A carregar lista de proibidos... - - Magnitude - Magnitude - - - Malformed CPID CPID Mal Formado - Organization Empresa - Project email mismatch Email de projeto incompatível - Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. Atenção: -paytxfee está definida com um valor muito elevado! Esta é a taxa que irá pagar se enviar uma transação. - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. Atenção: wallet.dat corrupto, dados recuperados! Wallet.dat original guardada como wallet.{timestamp}.bak em %s; se o seu saldo ou transações estiverem incorretos, deverá restaurar duma cópia de segurança. - Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. Atenção: erro ao ler wallet.dat! Todas as chaves foram lidas correctamente, mas os dados de transação ou entradas do livro de endereços podem estar em falta ou incorretos. - Error: Transaction creation failed Erro: Criação de transação falhou - Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. Erro: A transação foi rejeitada. Isto pode acontecer se algumas das moedas na sua carteira já tiverem sido gastas, por exemplo se as usou na cópia da sua wallet.dat, mas não foram marcadas como gastas aqui. - Failed to listen on any port. Use -listen=0 if you want this. Falhou a escutar em qualquer porta. Use -listen=0 se quiser isto. - Single Choice Escolha Única - Snapshot Process Complete! Processo de Snapshot Completo! - Snapshot Process Has Begun. Processo de Snapshot Iniciou. - To use the %s option Para utilizar as opções %s - %s, you must set a rpcpassword in the configuration file: %s It is recommended you use the following random password: @@ -6747,7 +5095,7 @@ rpcpassword=%s The username and password MUST NOT be the same. If the file does not exist, create it with owner-readable-only file permissions. It is also recommended to set alertnotify so you are notified of problems; -for example: alertnotify=echo %%s | mail -s "Gridcoin Alert" admin@foo.com +for example: alertnotify=echo %%s | mail -s "Gridcoin Alert" admin@foo.com %s, tem de difinir uma palavra-passe rcp no ficheiro de configuração: %s @@ -6758,31 +5106,26 @@ rpcpassword=%s O nome de utilizador e palavra-passa NÃO devem ser a mesma. Se o ficheiro não existir, crie-o com permissões de escrita. Também é recomendado que defina um alarme de notificação para que seja notificado de problemas; -por exemplo: alertnotify=echo %%s | mail -s "Gridcoin Alert" admin@foo.com +por exemplo: alertnotify=echo %%s | mail -s "Gridcoin Alert" admin@foo.com - Due to the failure to delete the blockchain data you will be required to manually delete the data before starting your wallet. Devido à falha na eliminação dos dados da cadeia de blocos, ser-lhe-á solicitado que elimine manualmente os dados antes de iniciar a sua carteira. - Failed to download snapshot as mandatory client is available for download. Falhou a transferência do snapshot porque existe uma atualização obrigatória da aplicação. - Failure to do so will result in undefined behaviour or failure to start wallet. Se não o fizer, o resultado será um comportamento indefinido ou uma falha no arranque da carteira. - Unable to download a snapshot, as the wallet has detected that a new mandatory version is available for install. The mandatory upgrade must be installed before the snapshot can be downloaded and applied. Não foi possível transferir o snapshot, porque a carteira detetou que uma versão obrigatória mais recente, está disponível para instalar. A atualização obrigatória deve ser instalada antes que o snapshot possa ser transferido e aplicado. - WARNING: Blockchain data may be corrupted. Gridcoin detected bad index entries. This may occur because of an unexpected exit, a power failure, or a late software upgrade. @@ -6805,7 +5148,6 @@ A sua carteira irá transferir novamente a cadeia de blocos. O seu balanço pode - You must set rpcpassword=<password> in the configuration file: %s If the file does not exist, create it with owner-readable-only file permissions. @@ -6814,307 +5156,242 @@ If the file does not exist, create it with owner-readable-only file permissions. Se o ficheiro não existir, crie-o com permissões de leitura. - Gridcoin version Versão do Gridcoin - Resetting block chain index to prepare for reindexing... Repondo o índice da block chain para preparar a reindexação... - Stage (1/4): Downloading snapshot.zip: Etapa (1/4): Transferindo o snapshot.zip: - Stage (2/4): Verify SHA256SUM of snapshot.zip: Etapa (2/4): Verificando SHA256SUM do snapshot.zip: - Stage (3/4): Cleanup blockchain data: Etapa (3/4): Limpar dados da cadeia de blocos: - Stage (4/4): Extracting snapshot.zip: Etapa (4/4): Extraindo o snapshot.zip: - Staking Only - Investor Mode Para Realizar Stake Apenas - Modo de Investidor - Staking Only - No Eligible Research Projects Para Realizar Stake Apenas - Sem Projetos de Pesquisa Elegíveis - Testnet-only version Versão de rede de testes apenas - Unknown error Erro desconhecido - Unknown Desconhecido - Staking Only - No active beacon A Realizar Stake Apenas - Beacon Inativo - Staking Only - Pool Detected A Realizar Stake Apenas - Pool detetada - Superblock Binary Size Super Bloco de Tamanho Binário - This update is A atualização está - Unknown poll response type. Tipo de resposta da sondagem desconhecida. - Unknown poll type. Tipo de sondagem desconhecida. - Unknown poll weight type. Tipo de peso da sondagem desconhecido. - None Nenhum - No current polls Sem sondagens - - Invalid amount for -paytxfee=<amount>: '%s' - Quantia inválida para -paytxfee=<amount>: '%s' + Invalid amount for -paytxfee=<amount>: '%s' + Quantia inválida para -paytxfee=<amount>: '%s' - - Invalid amount for -mininput=<amount>: '%s' - Quantia inválida para -mininput=<amount>: '%s' + Invalid amount for -mininput=<amount>: '%s' + Quantia inválida para -mininput=<amount>: '%s' - Initialization sanity check failed. Gridcoin is shutting down. Inicialização de verificação de sanidade falhou. O Gridcoin está a encerrar. - Wallet %s resides outside data directory %s. A carteira %s reside fora da diretoria de dados %s. - Verifying database integrity... Verificando integridade da base de dados... - Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. Erro ao iniciar o ambiente da base de dados %s! Para recuperar, FAÇA UMA CÓPIA DE SEGURANÇA DESSA DIRETORIA, depois remova tudo, exceto o wallet.dat. - wallet.dat corrupt, salvage failed wallet.dat corrupto, recuperação falhou - - Invalid -proxy address: '%s' - Endereço -proxy inválido: '%s' + Invalid -proxy address: '%s' + Endereço -proxy inválido: '%s' - - Invalid -tor address: '%s' - Endereço -tor inválido: '%s' + Invalid -tor address: '%s' + Endereço -tor inválido: '%s' - - Cannot resolve -bind address: '%s' - Não foi possível resolver o endereço -bind: '%s' + Cannot resolve -bind address: '%s' + Não foi possível resolver o endereço -bind: '%s' - - Cannot resolve -externalip address: '%s' - Não foi possível resolver o endereço -externalip: '%s' + Cannot resolve -externalip address: '%s' + Não foi possível resolver o endereço -externalip: '%s' - Invalid amount for -reservebalance=<amount> Quantia inválida para - reservebalance=<amount> - Error loading blkindex.dat Erro ao carregar blkindex.dat - Error loading wallet.dat: Wallet corrupted Erro ao carregar wallet.dat: Carteira corrompida - Error loading wallet.dat: Wallet requires newer version of Gridcoin Erro ao carregar wallet.dat: A carteira necessita de uma versão mais recente do Gridcoin - - Offline - Offline - - - Verifying checkpoints... Verificando checkpoints... - Wallet locked Carteira trancada - Wallet needed to be rewritten: restart Gridcoin to complete A carteira precisa de ser reescrita: reinicie o Gridcoin para concluir - Error loading wallet.dat Erro ao carregar wallet.dat - Importing bootstrap blockchain data file. Importação do ficheiro de dados da cadeia de blocos bootstrap. - Loading addresses... A carregar os endereços... - Error: could not start node Erro: Não foi possível iniciar o nó - Unable to bind to %s on this computer. Gridcoin is probably already running. Não foi possível ligar ao %s neste computador. O Gridcoin já está possivelmente a ser executado. - Unable to bind to %s on this computer (bind returned error %d, %s) Não foi possível vincular a %s neste computador (ligação retornou erro %d, %s) - Error: Wallet locked, unable to create transaction Erro: Carteira bloqueada, não foi possível criar transação - Error: Wallet unlocked for staking only, unable to create transaction. Erro: Carteira desbloqueada para realizar stake apenas, não foi possível criar transação. - Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds Erro: Esta transação devido à sua quantia, complexidade ou utilização de fundos recebidos recentemente, necessita de uma taxa de transação de pelo menos %s - Sending... Enviando... - Invalid amount Quantia inválida - - Warning: Please check that your computer's date and time are correct! If your clock is wrong Gridcoin will not work properly. + Warning: Please check that your computer's date and time are correct! If your clock is wrong Gridcoin will not work properly. Aviso: Por favor verifique que a data e hora do seu computador estão corretos! Se o seu relógio estiver incorreto, o Gridcoin não funcionará bem. - Vote signature failed. See debug.log. Assinatura da votação falhou. Ver debug.log. - Warning: Disk space is low! Aviso: Pouco disco em espaço! - - Unknown network specified in -onlynet: '%s' - Rede desconhecida especificada em -onlynet: '%s' + Unknown network specified in -onlynet: '%s' + Rede desconhecida especificada em -onlynet: '%s' - Insufficient funds Fundos insuficientes - Loading block index... A carregar o índice de blocos... - Loading wallet... A carregar a carteira... - Cannot write default address Impossível escrever endereço por defeito - Rescanning... Reexaminando... - Done loading Carregamento concluído - Error Erro diff --git a/src/qt/locale/bitcoin_vi.ts b/src/qt/locale/bitcoin_vi.ts index c68b47437f..454b9c557f 100644 --- a/src/qt/locale/bitcoin_vi.ts +++ b/src/qt/locale/bitcoin_vi.ts @@ -9,7 +9,21 @@ <b>Gridcoin</b> Gridcoin - + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or https://opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (https://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Đây là phần mềm thử nghiệm. + +Được phân phối theo giấy phép phần mềm MIT/X11, xem tệp COPYING đi kèm hoặc https://opensource.org/licenses/mit-license.php. + +Sản phẩm này bao gồm phần mềm do Dự án OpenSSL phát triển để sử dụng trong Bộ công cụ OpenSSL (https://www.openssl.org/) và phần mềm mã hóa được viết bởi Eric Young (eay@cryptsoft.com) và phần mềm UPnP được viết bởi Thomas Bernard. + + AdditionalFieldsTableDataModel @@ -33,7 +47,7 @@ &New - Tạo mới + &Tạo mới Copy the currently selected address to the system clipboard @@ -41,7 +55,11 @@ &Copy - Sao chép + &Sao chép + + + Show &QR Code + Hiển thị &mã QR Address Book @@ -51,12 +69,20 @@ &Delete &Xóa + + Copy &Label + Sao chép &nhãn dữ liệu + + + &Edit + &Chỉnh sửa + AddressTableModel Label - Nhãn d? li?u + Nhãn dữ liệu Address @@ -69,53 +95,197 @@ AskPassphraseDialog + + Passphrase Dialog + Hộp thoại cụm mật khẩu + + + Enter passphrase + Nhập cụm mật khẩu + + + New passphrase + Cụm mật khẩu mới + + + Repeat new passphrase + Nhập lại cụm mật khẩu mới + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + Nhập cụm mật khẩu mới vào ví. <br/>Vui lòng sử dụng cụm mật khẩu gồm <b>mười ký tự ngẫu nhiên trở lên</b> hoặc <b>tám từ trở lên</b>. + Encrypt wallet Mã hóa ví + + This operation needs your wallet passphrase to unlock the wallet. + Thao tác này cần có cụm mật khẩu ví của bạn để mở khóa ví. + Unlock wallet Mở khóa ví + + Change passphrase + Thay đổi cụm mật khẩu + + + Enter the old and new passphrase to the wallet. + Nhập cụm mật khẩu cũ và cụm mật khẩu mới vào ví + Confirm wallet encryption Xác nhận mã hóa ví + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Cảnh báo: Nếu bạn mã hóa ví và làm mất cụm mật khẩu, bạn sẽ <b>MẤT TẤT CẢ SỐ TIỀN CỦA MÌNH</b>! + + + Are you sure you wish to encrypt your wallet? + Bạn có chắc chắn muốn mã hóa ví của mình không? + Wallet encrypted Ví đã được mã hóa + + Gridcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Gridcoin sẽ đóng để hoàn tất quá trình mã hóa. Hãy nhớ rằng việc mã hóa ví của bạn không thể bảo vệ hoàn toàn tiền của bạn khỏi việc bị đánh cắp trong trường hợp máy bạn bị lây nhiễm mã độc (virus). + Wallet encryption failed Mã hóa ví thất bại + + The supplied passphrases do not match. + Cụm mật khẩu được cung cấp không khớp. + Wallet unlock failed Mở khóa ví thất bại - + + The passphrase entered for the wallet decryption was incorrect. + Cụm mật khẩu được nhập để giải mã ví không chính xác. + + + Wallet passphrase was successfully changed. + Cụm mật khẩu ví đã được thay đổi thành công. + + + Warning: The Caps Lock key is on! + Cảnh báo: Đang bật phím Caps Lock! + + BitcoinGUI Wallet + + &Overview + &Tổng quan + + + Show general overview of wallet + Hiển thị tổng quan ví + + + &Send + &Gửi + + + Send coins to a Gridcoin address + Gửi tiền đến một địa chỉ Gridcoin + + + &Receive + &Nhận + + + Show the list of addresses for receiving payments + Hiển thị các địa chỉ dùng để nhận thanh toán + + + &History + &Lịch sử + + + &Web Site + &Trang web + + + &GRC Chat Room + &Phòng chat GRC + GRC Chatroom Phòng chat GRC + + E&xit + T&hoát + Quit application Thoát ứng dụng + + &About Gridcoin + &Về Gridcoin + + + Show information about Gridcoin + Hiển thị thông tin về Gridcoin + + + &Options... + &Tùy chọn... + + + &Show / Hide + &Hiển thị / Ẩn + + + &Encrypt Wallet... + &Mã hóa ví... + Encrypt wallet Mã hóa ví + + &Change Passphrase... + &Thay đổi cụm mật khẩu... + + + &Unlock Wallet... + &Mở khóa ví... + + + &Lock Wallet + &Khóa ví + Lock wallet Khóa ví + + &Debug window + &Cửa sổ gỡ lỗi + + + &File + &Tệp + + + &Community + &Cộng đồng + %n active connection(s) to the Gridcoin network @@ -152,6 +322,10 @@ + + Warning: After the blockchain data is deleted, the wallet will shutdown and when restarted will begin syncing from zero. Your balance will temporarily show as 0 GRC while syncing. + Cảnh báo: Sau khi dữ liệu blockchain của bạn bị xóa, ví sẽ tắt và khi khởi động lại ví sẽ bắt đầu đồng bộ hóa lại từ đầu. Số dư tài khoản của bạn sẽ tạm thời hiển thị là 0 GRC trong lúc thực hiện đồng bộ hóa. + Close Confirmation Đóng xác nhận @@ -174,7 +348,7 @@ day - ngà + ngày hour @@ -206,10 +380,18 @@ Select All Chọn tất cả + + Tree &mode + &Chế độ cây + Amount Số lượng + + &List mode + &Chế độ danh sách + Address Địa chỉ @@ -220,7 +402,14 @@ (no label) - (ch?a có nhãn) + (chưa có nhãn) + + + + ConsolidateUnspentWizardSelectInputsPage + + Fee + Phí @@ -245,11 +434,11 @@ EditAddressDialog &Label - Nhãn dữ liệu + &Nhãn dữ liệu &Address - Địa chỉ + &Địa chỉ @@ -273,6 +462,32 @@ + + OptionsDialog + + &Port: + &Cổng: + + + &Window + &Cửa sổ + + + User Interface &language: + &Ngôn ngữ giao diện người dùng: + + + &Cancel + &Hủy + + + + OverviewPage + + Wallet + + + QObject @@ -312,15 +527,93 @@ + + QRCodeDialog + + QR Code Dialog + Hộp thoại mã QR + + + &Save As... + &Lưu dưới dạng... + + + Error encoding URI into QR Code. + Lỗi mã hóa URI thành mã QR + + + Save QR Code + Lưu mã QR + + + + RPCConsole + + &Information + &Thông tin + + + &Open + &Mở + + + 1 &hour + 1 &giờ + + + 1 &day + 1 &ngày + + + 1 &week + 1 &tuần + + + 1 &year + 1 &năm + + + + ResearcherWizard + + &Start Over + &Bắt đầu lại + + + + ResearcherWizardAuthPage + + &Copy + &Sao chép + + + + ResearcherWizardPoolPage + + &Copy + &Sao chép + + + + ResearcherWizardSummaryPage + + &Projects + &Dự án + + SendCoinsDialog Amount: Số lượng: + + S&end + G&ửi + (no label) - (ch?a có nhãn) + (chưa có nhãn) @@ -345,18 +638,18 @@ Amount - S? l??ng + Số lượng TransactionTableModel Address - ??a ch? + Địa chỉ Amount - S? l??ng + Số lượng Open for %n more block(s) @@ -369,15 +662,65 @@ TransactionView Label - Nhãn d? li?u + Nhãn dữ liệu Address - ??a ch? + Địa chỉ Amount - S? l??ng + Số lượng + + UpgradeQt + + &File + &Tệp + + + + bitcoin-core + + Invalid amount + Số tiền không hợp lệ + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Gridcoin will not work properly. + Cảnh báo: Vui lòng kiểm tra xem ngày và giờ trên máy tính của bạn có chính xác không! Nếu đồng hồ của bạn sai, Gridcoin sẽ không hoạt động bình thường. + + + Warning: Disk space is low! + Cảnh báo: Dung lượng ổ đĩa thấp! + + + Insufficient funds + Nguồn tiền không đủ + + + Loading block index... + Đang tải chỉ mục khối (block index)... + + + Loading wallet... + Đang tải ví... + + + Cannot write default address + Không thể ghi địa chỉ mặc định + + + Rescanning... + Đang quét lại... + + + Done loading + Đã tải xong + + + Error + Lỗi + + \ No newline at end of file