The Second Vatican Council, with its Dogmatic Constitution "Lumen gentium," and its Decrees on Ecumenism (Unitatis redintegratio) and the Oriental Churches (Orientalium Ecclesiarum), has contributed in a decisive way to the renewal of Catholic ecclesiolgy. The Supreme Pontiffs have also contributed to this renewal by offering their own insights and orientations for praxis: Paul VI in his Encyclical Letter "Ecclesiam suam" (1964) and John Paul II in his Encyclical Letter "Ut unum sint" (1995). The consequent duty of theologians to expound with greater clarity the diverse aspects of ecclesiology has resulted in a flowering of writing in this field. In fact it has become evident that this theme is a most fruitful one which, however, has also at times required clarification by way of precise definition and correction, for instance in the declaration "Mysterium Ecclesiae" (1973), the Letter addressed to the Bishops of the Catholic Church "ommunionis notio" (1992), and the declaration "Dominus Iesus" (2000), all published by the Congregation for the Doctrine of the Faith. The vastness of the subject matter and the novelty of many of the themes involved continue to provoke theological reflection. Among the many new contributions to the field, some are not immune from erroneous interpretation which in turn give rise to confusion and doubt. A number of these interpretations have been referred to the attention of the Congregation for the Doctrine of the Faith. Given the universality of Catholic doctrine on the Church, the Congregation wishes to respond to these questions by clarifying the authentic meaning of some ecclesiological expressions used by the magisterium which are open to misunderstanding in the theological debate.
First Question: Did the Second Vatican Council change the Catholic doctrine on the Church?
Response: The Second Vatican Council neither changed nor intended to change this doctrine, rather it developed, deepened and more fully explained it. This was exactly what John XXIII said at the beginning of the Council (1). Paul VI affirmed it (2) and commented in the act of promulgating the Constitution "Lumen gentium": "There is no better comment to make than to say that this promulgation really changes nothing of the traditional doctrine. What Christ willed, we also will. What was, still is. What the Church has taught down through the centuries, we also teach. In simple terms that which was assumed, is now explicit; that which was uncertain, is now clarified; that which was meditated upon, discussed and sometimes argued over, is now put together in one clear formulation" (3). The Bishops repeatedly expressed and fulfilled this intention (4).
Second Question: What is the meaning of the affirmation that the Church of Christ subsists in the Catholic Church?
Third Question: Why was the expression "subsists in" adopted instead of the simple word "is"?
Response: The use of this expression, which indicates the full identity of the Church of Christ with the Catholic Church, does not change the doctrine on the Church. Rather, it comes from and brings out more clearly the fact that there are "numerous elements of sanctification and of truth" which are found outside her structure, but which "as gifts properly belonging to the Church of Christ, impel towards Catholic Unity" (11). "It follows that these separated churches and Communities, though we believe they suffer from defects, are deprived neither of significance nor importance in the mystery of salvation. In fact the Spirit of Christ has not refrained from using them as instruments of salvation, whose value derives from that fullness of grace and of truth which has been entrusted to the Catholic Church" (12).
Fourth Question: Why does the Second Vatican Council use the term "Church" in reference to the oriental Churches separated from full communion with the Catholic Church?
Response: The Council wanted to adopt the traditional use of the term. "Because these Churches, although separated, have true sacraments and above all – because of the apostolic succession – the priesthood and the Eucharist, by means of which they remain linked to us by very close bonds" (13), they merit the title of "particular or local Churches" (14), and are called sister Churches of the particular Catholic Churches (15). "It is through the celebration of the Eucharist of the Lord in each of these Churches that the Church of God is built up and grows in stature" (16). However, since communion with the Catholic Church, the visible head of which is the Bishop of Rome and the Successor of Peter, is not some external complement to a particular Church but rather one of its internal constitutive principles, these venerable Christian communities lack something in their condition as particular churches (17). On the other hand, because of the division between Christians, the fullness of universality, which is proper to the Church governed by the Successor of Peter and the Bishops in communion with him, is not fully realised in history (18).
Fifth Question: Why do the texts of the Council and those of the Magisterium since the Council not use the title of "Church" with regard to those Christian Communities born out of the Reformation of the sixteenth century?
Response: According to Catholic doctrine, these Communities do not enjoy apostolic succession in the sacrament of Orders, and are, therefore, deprived of a constitutive element of the Church. These ecclesial Communities which, specifically because of the absence of the sacramental priesthood, have not preserved the genuine and integral substance of the Eucharistic Mystery (19) cannot, according to Catholic doctrine, be called "Churches" in the proper sense (20).


text:
Sainte-Thècle (Santa Tecla en el idioma español) es un municipalidad canadiense de la provincia de Quebec, ubicada en municipio regional de condado de Mékinac, sobre todo en la cuenca Batiscanie y en la región administrativa de Mauricie. Esta localidad  cuadrada es especialmente conocida por sus estaciones de todo sus 55 lagos que salpican la zona. Su bosque y el paisaje de montaña ofrecen vistas excepcionales a los turistas y veraneantes. Sainte-Thècle es también un paraíso para los vehículos de la caza, pesca, motos de nieve/todo terreno y otros deportes al aire libre. La iglesia, casa parroquial y el cementerio, situado en la colina dominante de la aldea es un patrimonio histórico de gran interés. Las industrias agrícolas y forestales han marcado su historia.

Geografía
Sainte-Thècle se encuentra en el cruce de las rutas 153 y 352. El camino 153, orientado norte-sur, que conecta Yamachiche de Lac-aux-Sables a través de Saint-Tite. En su camino a Sainte-Thècle, el camino 153 cubre la ruta de St. George Road (sur), Notre-Dame, St-Jacques y chemin St-Pierre del Norte. Si bien el camino 352 de Trois-Rivières a Saint-Stanislas y Saint-Adelphe, entonces llega a Sainte-Thècle por St. Thomas Road South, que termina en la intersección de la carretera 153 en el extremo sur de la localidad de Sainte-Thècle (cerca de la estación).

El municipio de Sainte-Thècle está encerrado por Saint-Tite (sur), Grandes-Piles (sur-oeste), Saint-Roch-de-Mékinac (sur-oeste), Trois-Rives (norte), Lac-aux-Sables (norte) y Saint-Adelphe (sureste). Casi todo el territorio de Sainte-Thècle es parte de Cuenca río Batiscan, excepto un área en el noreste (el límite de Trois-Rives) y otra pequeña área cerca del lago al noreste misionero.

Hidrografía

El territorio de Sainte-Thècle se caracteriza por cuatro cuencas de Batiscanie:

• el río Mekinac cuya ruta parte de Lago Mekinac fluya hacia el Saint-Maurice Río en Mauricie Medio. La parte norte de Canton Lejeune fluye hacia el río Mekinac, incluyendo el lago y el lago Botón Lejeune. Se une a la corriente a través del Lago Thom Bouchard, Lake George y el Lago Thom. Corriente Thom desemboca en el río Mekinac en el pueblo de Saint-Joseph-de-Mékinac.

• el Petite rivière Mékinac Nord (pequeño río al norte Mekinac) cuyo segmento norte tiene una longitud de 19 km. Este río tiene su fuente en Sainte-Thècle, de tercera Lago Champlain (3e lac Champlain). Las aguas fluyen hacia el sur, posteriormente, en el segundo lago, entonces el primer lago Champlain. El curso del río continúa hacia el sur, cruzando lagos Cobb-Dorval (a 2.4 km de la desembocadura del próximo lago) y Pelard (a 2,8 km de la desembocadura del pequeño lago Dorval). El límite de Sainte-Thècle y Grandes-Piles es justo al sur de Lago Pelard y el agua hasta el lago "Pedro" (à Pierre) y el pequeño lago Dorval (situado a 3 km del lago Roberge (Grandes-Piles). South Lago Cobb-Dorval, el río recoge otra secreción del oeste que vierte las aguas de los lagos de "embriones", "du Canard" (pato) y Button. Nicolás en el centro del lago, el río recibe el lado este, la salida del lago Fontaine (Grandes-Piles). Finalmente el río desemboca en un pequeño lago en el extremo noroeste del lago Roberge (Grandes-Piles). Este pequeño lago también recibe las aguas del segundo lago que Roberge descarga fluye hacia el sur este fin, la descarga de un centenar de metros del pequeño lago desemboca en el Lago Roberge;

• El rivière des Envies (río Antojos) cruzando el rango St. Joseph (dirección sur), teniendo su origen en Lake Traverse, es la mayor cuenca hidrográfica. Este río atraviesa el territorio de Saint-Tite (a través de los picos más grandes) Saint-Severin y desemboca en el río Batiscan para localidad de Saint-Stanislas (Les Chenaux);

• El Río Pierre-Paul se eleva en Lago Pierre-Paul, que se encuentra en la parte oriental del territorio de Saint-Tite. El curso principal del río describe un gran "Z" por una tierra eminentemente agrícola (y un bosque al principio de curso). El río corre primero al norte en Sainte-Thècle, el drenaje de las filas St. Thomas (Sur). El río hace una broma sobre dos lotes en Montañas San Jorge (del Sur). A partir de ahí, el río horquillas a 160 grados a la derecha para dirigirse hacia el sur, la recogida de la corriente de descarga Gagnon que drena parte de resonaron St George (Sur). El río atraviesa la carretera, y Charest corte diagonal seis lotes de terreno sonaron St-Thomas (sur). Su camino se cruza la frontera de la Saint-Adelphe y cortar nueve lotes de sonó St-Émile (Saint-Adelphe) y seis lotes en Montañas St-Pierre (Saint-Adelphe), antes de hacer un poco de broma a tres lotes en el cuarto noreste rango Rivière des Envies (en Saint-Tite). El Río Pierre-Paul y sucursales a 120 grados a la izquierda para volver al norte a través de cuatro lotes de la rang St-Pierre Saint-Adelphe. Su carrera corta ocho lotes en Montañas St-Alphonse (Saint-Adelphe) y algunos Ranking suroeste lotes río Batiscan, antes de desembocar en el río Batiscan para la altura de la localidad de Saint-Adelphe (lado suroeste).

Mientras Piché Creek drena gran parte del rango St. Thomas (norte-sur) por el corte perpendicular a los lotes por carretera 352 (Rompré carretera) donde se convierte en "Brazo de Pierre-Paul River". Este pequeño río ramas al sur y cruzar el camino de flujo St-Emile en el Río Pierre-Paul (aproximadamente  de la boca de este último, que desemboca en el Batiscan) La investigación llevada a cabo por.

• El río Tawachiche tiene una ruta norte-sur  en su totalidad en el término municipal de Lac-aux-Sables. El río fluye a través de la Zec Tawachiche para desplazarse hacia el norte-este de la aldea's Hervey Junction, donde hay hermosas cascadas. A continuación, el río corre a lo largo de la frontera suroeste del municipio de Lac-aux-Sables y Sainte-Thècle, que desemboca en el río Batiscan, en el borde de Lac-aux-Sables y Sainte-Thècle, en un área designada el "Pee-Wee". Su principal afluente es el río West Tawachiche, que desemboca en el río Tawachiche para Audy.

En la historia de los nativos americanos, estos tres ríos se considera que han servido como ruta de transporte (incluyendo canoas o en las carreteras de hielo) para llegar a los lagos y ríos de aguas arriba. Muchos diques de los castores se desaceleraron sus tasas. Estos ríos también sirvieron estacionalmente transporte de madera de flotación y algunos aserraderos se establecieron en su carrera.

El Batiscan que fluye al sur sobre 196 km, se eleva en el Lago Isla y Haute-Mauricie. Fluye a través de la Portneuf Wildlife Sanctuary a Rivière-à-Pierre, Notre-Dame-de-Montauban, Lac-aux-Sables, Sainte-Thècle (límite), Saint-Adelphe, Saint-Stanislas, Saint-Narcisse, Sainte-Geneviève-de-Batiscan y Batiscan.

Demografía locales

Viviendas particulares ocupadas por residentes permanentes (2011): 1157 (de un total de 1413 unidades).

Lengua materna:
 Francés como primera lengua: 98,2%
 Inglés como primera lengua: 0,4%
 Inglés y francés como primera lengua: 0,4%
 Otros idiomas nativos: 1,0%

Principales lugares de interés

 Parc St-Jean-Optimiste, situada en el pueblo, en el borde del Lac Croche (parte sur del lago). Este sitio contiene una playa pública municipal, una hermosa fuente de agua iluminada en el centro del lago, un embarcadero para embarcaciones de recreo, un aterrizaje, un centro de recreación, mesas de pícnic, una pelota de volley ... y el paso "Laurent Naud", situada en las orillas del Lac-Croche (entre la rue Du Pont y Parc de St-Jean-Optimiste). En invierno, la pista está patinando popular. Varios eventos sociales y deportivos se llevan a cabo regularmente en el Parque St-Jean-Optimiste.
 Iglesia construida en 1903-1905, situado en la colina más alta del centro del pueblo. Construido bajo la dirección del sacerdote Maxime Masson, la iglesia de Sainte-Thècle es uno de los mejores del patrimonio religioso de la Mauricie y Quebec.
 Cementerio de arriba  (designado "Cementerio de Masson"), detrás de la iglesia. Cuenta con un camino de la cruz tallada en piedra, una hermosa pesadilla y muchos monumentos antiguos que recuerdan el pasado de la vida de los antepasados. Nota: El cementerio a continuación se designa como "cementerio Janelle", que evoca la obra de la vida del sacerdote Michel Janelle de Sainte-Thècle.
 Landing Pública en Lago Jesuite, en la parte sur del lago, cerca de la boca.
 Landing Pública en Lac-aux-Chicots (situado en la carretera de St-Pierre-sur), cerca de la aldea).
 El paseo Chnabail lago (accesible por carretera desde la Lago Jesuite), que ofrece un paseo por el bosque para descubrir el desierto.
 Club de esquí "Le Geaie Bleu" (El Blue Jay), ubicado en 2501 chemin Saint-Michel del Norte, Sainte-Thècle. Este centro proporciona  de pistas acondicionadas.
 Sugarbush. Sainte-Thècle tiene varios arce para la producción de jarabe de arce en la primavera. Algunos de arce tiene un espacio para dar cabida a grupos y ofrecen comidas, incluyendo arce "Chez Angelo y Anita", situada en 1631, chemin de Saint-Georges, Sainte-Thècle.
 Camping "Domaine Lac et Forêt" (Dominio y Lake Forest), que se encuentra en Saint-Pierre-graduación del Norte, que ofrece actividades para todos los grupos de edad: voleibol, baloncesto, balón prisionero, hockey, juegos (interior y exterior) y una piscina de olas gigantes...

Además, los visitantes pueden beneficiarse Sainte-Thècle muchos lagos para pasear en bote, senderos para motos de nieve o ATV, la caza y la pesca, camping y resort.

Municipal Cronología

  del municipio de la parroquia de Sainte-Thècle fue oficialmente establecida a raíz de la publicación del decreto del Gobierno en el Boletín Oficial Quebec (Gazette officielle du Québec).
  se crea el municipio poblado de Sainte-Thècle y su territorio (la ciudad desde arriba y desde la estación) se separa del municipio de la parroquia.
 1958: pueblo el sector inferior se encuentra el municipio de parroquia y se fusiona con el municipio aldea.
 1 de enero 1982: aplicación de la Mekinac MRC (municipalidad regional de condado), que a su vez sustituye a la corporación del condado que se estableció en 1855. El MRC es una organización Mekinac supramunicipal cuyo territorio incluye todos los municipios área Mekinac. Los poderes del MRC se basan en ambas potencias obligatorias previstas por la ley y las habilidades adicionales de acuerdo a la voluntad de los municipios de su territorio para compartir servicios.
 7 de junio 1989: Fusión entre el municipio de la parroquia y el pueblo de Sainte-Thècle para formar el municipio de Sainte-Thècle.

Escuela Cronología

 1878: creación del primer consejo escolar de Santa Tecla. La primera reunión de la junta escolar se llevó a cabo 4 de marzo de 1878 en la residencia de Theophile Magnan.
 1915: la separación del territorio de Sainte-Thècle dos tablas: la aldea y parroquia.
 1949: fusión de las dos tablas.
 1965, la Fundación CSRM (Commission scolaire régionale de la Mauricie) para servir a toda la educación secundaria, vigente a partir del 1 de julio de 1965. Si bien la Junta Escolar de Sainte-Thècle sigue tutor pedagógico nivel primario.
 1969: el cese de la enseñanza secundaria y tres más en junio de 1969 en Sainte-Thècle. Ahora, esta enseñanza es el "École secondaire Paul Le Jeune" en Saint-Tite, que comenzó en septiembre de 1969.
 1 de julio 1972: Junta fusión Escuela de Santa Tecla con el "Commission scolaire de Normandie" (Consejo Escolar Normandía) que ya fue responsable desde 1969 para la enseñanza primaria en todas las demás parroquias de la zona llamada Normandía.
 1 de julio 1998: El Consejo Escolar de Normandía se disolvió el 30 de junio de 1998 y dar paso a 1 en julio de 1998 en la "Commission scolaire de l'Énergie" (Comisión de Energía de la Escuela), que se encarga de administrar primaria y secundaria en el mismo territorio que la antigua CSRM (ya sea Mont-Carmel y de Parent (Quebec), Abitibi).

Cronología religiosa

 : la erección canónica de la parroquia católica de Sainte-Thècle
  - Don por escritura de Lord John Price mucho Fábrica Sainte-Thècle, a fin de construir una capilla.
 1877 en 1879 - La construcción de la capilla del pueblo de abajo.
 1880 - registros abiertos actos de bautizos, matrimonios y entierros de Sainte-Thècle. Anteriormente, los actos relativos a los residentes de Lac-aux-Chicots fueron de registro de Saint-Tite.
 1893 - Ampliación de la capilla del pueblo de abajo, después de un nuevo decreto del obispo de 6 de octubre de 1892. Esta expansión ha permitido la incorporación de 75 camas, mientras que inicialmente la capilla incluyó 97 escuelas dentro de su recinto.
 1903 - Selección del sitio de la futura iglesia y comenzar la construcción de la iglesia.
 1903 - Consultar Maxime Masson, 6 de febrero de 1903, como párroco de Sainte-Thècle. Su tratamiento duró 52 años.
 1904 - Aprobación de 18 de noviembre de 1904 el nuevo cementerio en la cima de la colina más alta entre dos pueblos: la estación y uno en la parte inferior.
  - último entierro en el cementerio del pueblo de abajo. Se trata de los restos de Marie Paquin, esposa de François Béland.
  - La primera celebración religiosa en la nueva iglesia. Venta bancos se convirtió en el mismo domingo después de la gran masa.
 1905 - Construcción de Estaciones de la Cruz en el interior de la iglesia.
 1907 y 1908 - Erección de la Cruz en la sacristía.
 1914 - Adquisición del gran órgano de la iglesia, en sustitución del antiguo órgano, procedente de la capilla.
 1932 - Nueva promoción de acabado dentro de la etapa de la iglesia, incluyendo el famoso pintor Louis Edward Monty.
 1938 - hecha por el sacerdote Maxime Masson un cemento león, instalada en un pedestal fuera de la zona norte-este de la iglesia, que simboliza la "Fabrique de Sainte-Thècle", se libera de la deuda generada por la construcción de la iglesia desde 1903 hasta 1905.
  - Una tormenta derribó las torres gemelas de la iglesia de Sainte-Thècle. Varias casas y otros edificios fueron dañados.
  - Inicio de las obras de construcción de los cuadros de las paredes y el techo de la iglesia, de Louis Edward Monty, artista de Montreal. The Cure Maxime Masson da cuenta de las pinturas en el techo de la sacristía.
  - El fin del párroco de 52 años Maxime Masson 15 de octubre 1867 en  Saint-Justin - 2 de octubre 1960 en Pointe-du-Lac).
  - La instalación de un nuevo altar en la capilla mayor de la iglesia para ser el celebrante de cara al público.
 1974 - Instalación de la piedra de recuerdo en el parterre frente a la iglesia, al final de las festividades del centenario canónico y civil de Sainte-Thècle. Esta piedra se movió en 2017 en el parterre frente al presbiterio.
 1983 - Fin de la cura (1962-1985) de André Morin (nacido el 24 de febrero de 1907 en Lac-à-la-Tortue.
 1987 - Reconstitución del altar en el coro de la iglesia.
 Febrero de 1993 - La iglesia fue utilizada como el escenario para el rodaje de la boda en la serie de televisión "Blanche" en Radio-Canada.
  - Inauguración de la fuente frente a la iglesia, en el mismo sitio que la antigua fuente de la época del sacerdote Masson. - Ampliación de la rue St-Jacques para crear plazas de aparcamiento delante de la iglesia.
  - Creación de la nueva fábrica de la parroquia de Saint-Coeur-de-Marie, incluidas las fábricas de Notre-Dame-des-Anges, Saint-Eloi-les-Mines, Saint-Rémi-du-Lac-aux-Sables, St. Leopold de Hervey-Junction, St. Thecla y St. Adelphe.
  - Inauguración de la nueva fábrica en presencia del Obispo de la Diócesis de Trois-Rivières, el Obispo Luc Bouchard.
  - El final de los 33 años de edad de Gérald Baril (2.º más largo en la historia de Sainte-Thècle), desde 1985.
  - El nuevo sacerdote presidente, el padre Benoit Muhindo Matiri, de la parroquia de Saint-Coeur-de-Marie asumió el cargo.
 Verano de 2018: renovación del interior del Calvario del cementerio de Sainte-Thècle.

Moneda

"Pasar por sembrar la buena".

Armas de Sainte-Thècle

Desde mediados del siglo de 20th, la ciudad de Sainte-Thècle utiliza este escudo tripleta que proviene de la "Collège des armoiries du Canada" (Escuela de Armas de Canadá). Su interpretación original era teñida con el espíritu del cristianismo. El escudo fue lanzado el 14 de abril de 1958, el diario regional "Le Nouvelliste" (publicado Trois-Rivières, QC). 17 de enero de 1973 René Veillette resumió su interpretación en una columna en la historia de Sainte-Thècle, en el periódico Le Dynamique (El Dinámica) (editado Saint-Tite, QC). Esta interpretación ha sido adaptada por el historiador Gaetan Veillette en 2012.

Leucomas en la parte superior de la pantalla del triángulo simboliza los santos y los héroes de la historia, cuyo ejemplo ha inspirado a la moral. Ampliamente utilizado en hiéraldisme la media de oro brillo, la justicia, la fe, la fuerza y la consistencia. En el centro de la primera tripleta, el corazón significa bondad y dedicación, recordando la vida y obra de Thecla parroquia patrón. La corona colocada sobre el corazón evoca su santificación.

La segunda tripleta de azul el color azul simboliza la pureza. El árbol es la madera que ha dominado la economía local con la industria de la agricultura en la historia. Este árbol está plantado en una colina, lo que indica el punto más alto del pueblo, es el sitio de la iglesia.

En la tercera tripleta heráldico, derecha, abejas incorporan a la fuerza laboral y valiente. Ser reconocido como abejas laboriosas inspiran respeto. En armonía con la naturaleza, su función es fundamental en el ecosistema. El fondo rojo se muestra la solidaridad y la perseverancia de las personas a través de eventos y asuntos de la comunidad.

La hojas de arce en el fondo caracterizan la belleza y el simbolismo de este árbol muy común en Sainte-Thècle. Evocan los muchos maple producir jarabe de arce legendaria. La hoja de arce es también el emblema del país.

El estandarte de la parte inferior ofrece la moneda oficial de Sainte-Thècle: "Pasa por sembrar la buena". Este lema refleja una actitud cívica que todos deben adoptar todas las acciones de su vida. Por último, la cinta roja que une a las dos ramas de arce es un signo de unidad.

Toponimia

El nombre de Sainte-Thècle se atribuyó a la parroquia católica, los municipios (parroquia y la ciudad) y las juntas escolares locales (parroquia y ciudad) de la ciudad de Sainte-Thècle. Este nombre viene de Santa Tecla, virgen y mártir del , se convirtió al cristianismo y educado por Paul durante su primer viaje misionero. Tecla nació en Isauria de Turquía. Santo Tite y Santa Tecla que vivió al mismo tiempo, se eligió el nombre de la virgen de la erección canónica de la parroquia de Oriente Mauricie por el decreto del 15 de marzo de 1873 promulgado por el obispo Louis-François Richer Lafleche, obispo diócesis de Trois-Rivières. Por otra parte, Moises Proulx, pastor de la Saint-Tite sirvió la parroquia de Sainte-Thècle hasta 1880, hasta la llegada del primer pastor residente.

Los topónimos de las filas de la parroquia representa el impulso de la cristiandad del  San José (Saint-Joseph), San Miguel (Saint-Michel), San Pedro (Saint-Pierre), San Jorge (Saint-Georges) y St. Thomas (Saint-Thomas). La parte oriental de esta última se ha relacionado con el municipio de Sainte-Thècle, en 1891.

Las principales arterias de la ciudad de antaño son Notre-Dame, Saint-Jacques, Masson, Grenier, Lacordaire, Tessier, Estación (de la Station), y Du Pont. La última calle debe su designación flotando en el lago Croche, que conecta el pueblo a baja rang St-Michel puente (norte). Con la expansión del pueblo, los topónimos de nuevas calles era un patronímico común: calles Bédard, Veillette, Valle, Piché, Plaza Proteau, Plaza Cloutier, camino Marcotte, camino Marchand... Street Centennial fue erigido en los principales festivales 1973 a 1974, de forma paralela a la rue Villeneuve. Varias carreteras han sido designados en función de su ruta de contexto geográfico del bucle, el Lago Jesuite de Lake Traverse, lago Aylwin, municipio Lejeune, el lago Button ... La carretera Joseph Saint-Amant en Canton Lejeune honra este hombre de negocios de Saint-Tite, que ha contribuido en gran medida a la industria forestal, el dueño del aserradero en la ciudad de Saint-Tite.

Charest carretera (designado como un homenaje a Florent Charest, cuya familia vivía en Sainte-Thècle, en la esquina de St Thomas Road y Rompré carretera), la carretera que une St Thomas Road Lago Pierre-Paul (en Saint-Tite). Un segmento de aproximadamente  esta ruta fue abandonado en la década de 1970, a partir de la carretera Lago Pierre-Paul. La carretera Rompré (ahora un segmento de la Ruta 352) conecta el camino sonó St Thomas Road en St-Émile (Saint-Adelphe).

Al final del  , el pueblo de Sainte-Thècle fue desempate en dos áreas principales: el pueblo más bajo (el más antiguo, que se encuentra entre el lago Croche y lago-aux-Chicots) y el pueblo de la estación (que se formó por la estación de tren, llegó a Sainte-Thècle en 1887). Por último, la construcción de la iglesia en 1903, engendró a la construcción de calles Saint-Jacques y Masson, creando una tercera aldea.

Personalidades relacionadas con la localidad

 Eric Bedard (1976- ), campeón olímpico en patinaje de velocidad 1998 a 2006.

 Bruno Bordeleau (1868 - 1929), médico, alcalde de la localidad de Santa Tecla, y MLA registrador de Champlain.

 Josaphat Groleau (1893-1993), hombre de negocios en la industria de la madera, la municipalidad de alcalde de la localidad durante los tres períodos 1927-1931, 1947-1955 y 1960-1965. Fue presidente de la "Commission scolaire du village" (junta escolar de la aldea) 1947-1949. Terminó su carrera pública como alcaide bautismos.

 Maxime Masson (1867-1960), párroco de Sainte-Thècle, 1903-1955 y Presidente de la "Commission scolaire du village" (Junta Escolar de aldea de Sainte-Thècle) 1915-1947.

 Laurent Naud (1909-1992) hombre de negocios en la industria maderera y el comercio.

 Yvon Rivard (1945- ), un Canadiense escritor, nacido aquí en 1945. Es ganador en dos ocasiones del Gobernador General del Gobernador, recibiendo el Premio del Gobernador General por la ficción en lengua francesa en 1986 por  Los silencios del coro, y el Premio del Gobernador General por la no ficción en lengua francesa en 2013 por Aimer, enseñador.

 Alphée St-Amand (1903-1983), alcalde, jefe de bomberos, ambulancia jefe, funeral, dueño del taller, corporativo y líder comerciante textil.
 Benoît Tousignant (1927-2015), cardiólogo que ejerció en Trois-Rivières de 1964 a 1991.
 Jeffrey Veillet (1881-1946), empresario en la industria maderera y el comercio.

Galería de fotos

Publicaciones sobre la historia de Sainte-Thècle
 "Répertoire des baptêmes de Sainte-Thècle" (Directorio de bautismos de Sainte-Thècle) (1880-2012), incluyendo 182 actos de registro de Saint-Tite (vecina parroquia) 1869-1880. Publicado por la "Fabrique de Sainte-Thècle" (Fábrica de Sainte-Thècle), este libro tiene 354 páginas y 11135 bautizos.
 "Répertoire des naissances et des baptêmes de Sainte-Thècle" (Directorio de nacimientos y bautismos de Sainte-Thècle) (1880-1940), publicado en 2001, 262 páginas. Autor: Jacques Delisle. (Agotado Edition)
 "Répertoire des mariages de Sainte-Thècle" (Directorio de bodas de Sainte-Thècle) (1880-2004)", publicado en 2005 por la "Fabrique de Sainte-Thècle", 52 páginas. Autores: Yolande Saint-Amand, André B Veillette. Colaboradores: Andréanne, Daniel, Gaetan y Loraine Veillette.
 "Répertoire des mariages de Sainte-Thècle" (Directorio de matrimonios de Sainte-Thècle) (1880-1973)", publicado en 1974 en el centenario de Sainte-Thècle, 149 páginas. Co-autores: Nicole V. Béland, Daniel Veillette, Gaétan Veillette, René Veillette y Yolande St-Amand-Veillette. (Agotado Edition).
 Primero «Annexe au répertoire des mariages de Sainte-Thècle" (Anexo del "Directorio de matrimonios de Sainte-Thècle) (1974-1979)", que contiene 169 bodas. Autor: Yolande Saint-Amand-Veillette (agotado Edition).
 Segundo "Annexe au répertoire des mariages de Sainte-Thècle" (Anexo matrimonios Directorio de Sainte-Thècle) (1974-2004), publicado en 2005, 52 páginas. Autores: Yolande Saint-Amand B André Veillette. Colaborador: Andréanne Veillette.
 "Obituaire Lac-aux-Chicots - Sainte-Thècle 1870-1975", Éditions du Bien Public (Publicación de Bien Público), publicado en 1976 por Genevieve Leblanc y Marie-Ange B. Plamondon. 152 páginas. (Agotado Edition).
 Primer Anexo titulado "Obituario Lac-aux-Chicots-Sainte-Thècle 1975-1979", Éditions du Bien Public (Publicación de Bien Público), p. 153-176, publicado en 1980 por Genevieve y Marie Leblanc Angelo B. Plamondon. Este apéndice contiene el censo especial realizado en 1895 por el sacerdote Michel E. Jannelle. (Agotado Edition).
 Segundo Anexo "Obituaoire Lac-aux-Chicots-Sainte-Thècle 1975-2003", p.170-289, (Agotado Edition)
 Monografía de Centenario titulado "Une ville du nord, Sainte-Thècle, cent ans d'histoire" (Una ciudad del Norte, Sainte-Thècle, cien años de historia) - 1874-1974, Éditions du Bien Public (Publicación de Bien Público), 229 páginas, publicado 03 1974 durante las celebraciones del centenario de Sainte-Thècle. Texto: Dr. Jean-René Marchand. Documentación: Charles Magnan. Colaboradores: Michelle Trepanier y Padre Étienne Morin, op
 Volumen "Sainte-Thècle - Comté de Champlain" (Condado de Champlain)" contiene los censos de 1886, 1891, 1895, 1896 y 1897 de Sainte-Thècle. Publicado en Trois-Rivières en 1987. 320 páginas. Compilado por Brigitte Hamel S.C.O.
 "Des semailles aux glanures : répertoire des objets anciens de Ste-Thècle" (La siembra de la rebusca: directorio de las antigüedades de Sainte-Thècle). Textos redacción, Odette St-Amand bajo la dirección de Armande Rompré-St-Amand. Publicado por el "Comité socio-cultural de Sainte-Thècle", 1984, Imprimerie Arquienne (Arquienne impresión).
 Volumen "Sainte-Thècle - Le temps d'une vie mémorable… pendant un quart de siècle - 1935 à 1960" (Sainte-Thècle - Tiempo para una vida memorable... por un cuarto de siglo - 1935-1960). Autor: Fernando Cloutier. 295 páginas. Publicado en agosto de 2012 a la autora.
 Libro "Sainte-Thècle - Familles du Lac Travers 1955 (Rang St-Joseph)" (Sainte-Thècle - Familias de Lac Travers 1955 (Rang St-Joseph)), por Fernand Cloutier, 2018, 46 páginas - Fotografías: Claude Naud. Publicado en 2018 por el autor.
 Libro "Sainte-Thècle - Familles "Haut du Lac Sud" 1950 (Rang St-Pierre Sud)" (Sainte-Thècle - Familias "Haut du Lac Sud" 1950 (Rang St-Pierre Sud)), por Fernand Cloutier, 2019, 96 páginas - Colaboradore: Myriam Bédard, edición y diseño gráfico. Publicado en {2019 por el autor.
 Libro "Sainte-Thècle - Familles "Nord du lac" 1950 (Rang St-Michel Nord)" (Sainte-Thècle - Familias "Norte del lago" 1950 (Rang St-Michel Norte)), por Fernand Cloutier, 2020, 98 páginas - Colaboradore: Myriam Bédard, edición y diseño gráfico. Publicado en {2020 por el autor.
 Libro "Sainte-Thècle - Familles "Bas du Lac Sud" 1950 (Rang St-Michel Sud)" (Sainte-Thècle - Familias "Bas du Lac Sud" 1950 (Rang St-Michel Sud)), por Fernand Cloutier, 2020, 82 páginas - Colaboradore: Myriam Bédard, edición y diseño gráfico. Publicado en 2020 por el autor.
 Libro "Sainte-Thècle - 1950 - Rang St-Thomas Sud", por Fernand Cloutier, 2019, 94 páginas - Colaboradore: Myriam Bédard, edición y diseño gráfico. Publicado en 2020 por el autor.
 Libro "Sainte-Thècle - 1950 - Rang St-Thomas Nord''", por Fernand Cloutier, 2020, 139 páginas - Colaboradores: familiares de Fernand Gravel y Louiselle Lefebvre. Collaboratrice: Myriam Bédard, edición y diseño gráfico. Publicado en 2020 por el autor.

Referencias

Véase también

 Anexo:Localidades de Quebec
 Mékinac
 Franco-canadienses

Enlaces externos
 Sitio oficial de la municipalidad (en francés)

Municipios de Mékinac

redpajama_set_name: RedPajamaWikipedia


text:
using System.Collections.Generic;

namespace Cumulus.Configuration
{
    internal interface IValidatableConfigurationSetting
    {
        IEnumerable<string> Validate();
    }
}

redpajama_set_name: RedPajamaGithub


text:
Aspiring Speech-Language Pathologist Hopes to Improve Quality of Life for People with ALS
By Jessica Welsh
Updated on May 20, 2016
Abby Isabelle is a senior Communication Science and Disorders major originally from Lufkin, Texas. After working in agriculture and wildlife for a few years, she chose to come back to school and pursue a new career path.
"I decided to go to MU because I wanted to make a career change and the University has a great reputation. I met with the faculty in my department prior to enrolling, and I was encouraged because they were very supportive," Isabelle said.
Isabelle realized that what she really wanted to do was work with people, and she couldn't get that experience in her original field. Through volunteering with her church at nursing home facilities for the elderly, she discovered her true passion.
"Many of the people I visited had experienced neurological injuries, such as a stroke, or had another type of neurological impairment," Isabelle said.
"I saw how hard it was for them to communicate with their family members and with me and that is when I started thinking about being in this field and how rewarding it would be to help people with something as basic as communication: a part of life that I used to take for granted."
After she returned to school, Isabelle knew that she wanted to get involved with research so that she could see first-hand how research can be used to inform the content she learned in her courses and also how the things she was learning in class could be applied to the research realm and the clinical world.
She was particularly interested in a neuroscience class, so her professor put her in touch with her current faculty mentor, Dr. Mili Kuruvilla-Dugdale.
As soon as she began working in Dr. Kuruvilla-Dugdale's lab, she was able to start fulfilling her desire to work with people who have speech disorders.
"I assisted in the whole process of collecting speech data. I thought it was really neat that right off the bat I was able to interact with people and be involved in the research process," Isabelle said.
Isabelle is involved with research that focuses on speech disorders in people with ALS with an emphasis on evaluating the effects of clinical speech treatment techniques on articulatory motor control. The ultimate aim of this research is to help improve and maintain speech intelligibility for those with progressive speech loss due to ALS and Parkinson's. She will present her research at the Undergraduate Research and Creative Achievements Forum on April 26.
Isabelle thinks it's important for people to realize that clinical research can fill gaps in knowledge that in the long-term will lead to improvements in assessment and treatment that can help reduce the burden of communication disorders.
"When I first started in this field, I kept hearing that there's a need for more research, probably because people aren't aware of all of the opportunities and all the needs that exist," Isabelle said.
As a student in the health professions, Isabelle realized that research in her field could significantly help improve the lives of people with communication disorders.
"There is such a need, especially in the health professions, because you're making a big difference in the lives of people that have different types of disorders and impairments," Isabelle said.
Isabelle sees her own research being able to make a difference for the people with ALS that she works with, and hopes that she'll be able to improve their quality of life.
"Unfortunately ALS is a progressive disease and speech declines rapidly, but if we can give them a mechanism to improve or maintain their intelligibility for a longer period, they'll be able to communicate better and also participate in treatment and health care decisions," Isabelle said.
Not only does she see her research making a difference in the lives of people, it also helps her understand and apply her coursework.
"After working in Dr. Kuruvilla's lab, I have a better understanding of the field in general and also of the information that I am learning in my courses … everything starts coming together when you are aware of the research process behind the information, particularly clinical disorders, assessment, and treatment that we learn about in class ," Isabelle said.
Isabelle recommends that undergraduate researchers make the most of their experience, even if it's just taking advantage of the learning process.
"I would say take advantage of every opportunity that you can. Whether it's conference presentations, manuscripts, or submitting proposals for different awards or grants," Isabelle said.
"Even if you don't receive them, the process of designing a study and writing a proposal is a great learning experience."
Upon graduation, Isabelle will move on to attend graduate school at MU and then hopes to pursue a career as a speech language pathologist in a rehabilitation facility.

redpajama_set_name: RedPajamaCommonCrawl


text:
Home Top News PM Shehbaz underlines infinite potential in Pakistan during address to Turkiye-Pakistan Business...
PM Shehbaz underlines infinite potential in Pakistan during address to Turkiye-Pakistan Business Council
Istanbul: Prime Minister Shehbaz Sharif Saturday urged Turkish companies to invest in Pakistan, as the infinite potential between the two brotherly countries should also be reflected in bilateral trade and business.
PM Shehbaz was addressing the Turkiye-Pakistan Business Council meeting on Saturday, a day after reaching Turkiye on a two-day official visit.
During the address, PM Shehbaz reassured that his government would fully provide a hassle and "red tape-free environment" to Turkish investors. He informed that during his meeting with President Recep Tayyip Erdogan, it was conveyed that more Turkish companies were eager to come to Pakistan.
Regarding the delay in payment to investors, the Prime Minister said that it was regrettable that in the past regime, the Turkish companies that had invested in Pakistan were not given their due payments.
He pledged to expedite work on the "Trade and Goods Agreement" to further promote the bilateral trade and business relations between the two brotherly countries.
"Pakistan and Turkiye have signed an MOU to enhance the bilateral trade volume up to $5 billion in the next three years," he said
Turkiye's annual trade stood around $250 billion, but the trade between Pakistan and Turkiye is hovering around one and half billion dollars which had been peanuts while considering the immense potential," he added.
He also made a pitch to Turkish entrepreneurs to invest in a 10,000-megawatt solar power project for Pakistan, saying "my investor is my master".
PM Shehbaz also expressed his government's resolve to cut down "very expensive" imports of oil and petroleum products, on which $27 billion was spent last year. "We simply can't afford this."
He explained, his government had invited foreign investment at a conference in Islamabad around a month and a half ago for a 10,000MW solar power project.
"It's not just a paper, or a talk, or a feasibility," he said about the project. "I, along with my colleagues, […] am committed to this philosophy that we shall implement this scheme with in letter and spirit with our own resources, with investment from Turkiye, from China, from Saudia Arabia, from Qatar, from the UAE (United Arab Emirates), from the United States of America, from wherever."
He assured the investors that the Pakistan government would create a conducive, enabling and friendly environment for them to invest in the project.
Pakistan, Turkiye reaffirm commitment for $5 billion trade in 3 years
Previous articlePakistan, Turkiye reaffirm commitment for $5 billion trade in 3 years
Next articleWill I be able to download apps from Google Play Store after December 1?
Fawad remanded into police custody for 2 days
PPP to issue legal notice to Imran over allegations against Zardari
Arab-American leaders urge Blinken to hold Israel accountable
Turkey alerts citizens to risk of 'Islamophobic attacks' in US, Europe January 30, 2023
'Ideology of hate' consuming India: Gandhi's grandson January 30, 2023


I met with Emma and Ante on Friday for an afternoon session leading up to their wedding this weekend at Mt Lofty House. An image from our time on Friday. Will be a cracking wedding.
More to come before next weekend.


text:
Acerus Announces Launch of NATESTO® Specialty Sales Team in the United States
Acerus Pharmaceuticals Corporation (TSX:ASP, OTCQB:ASPCF), a specialty pharmaceutical company focused on the commercialization of novel prescription products for men's health, today announced the launch of a dedicated sales team to promote the Company's key product, NATESTO® (testosterone nasal gel), to urologists and endocrinologists across the United States.
The 22 specialty sales representatives will target high-prescribing (decile 6-10) medical practitioners who currently treat men with hypogonadism. Acerus, in partnership with Syneos Health, has equipped its U.S. team with a suite of digital technologies that will allow reps to conduct virtual meetings and customer engagements, given varying state rules regarding COVID-19 restrictions. In addition, as per the terms of the revised partnership agreement between Acerus and Aytu BioScience, Aytu will focus their own U.S. sales team (currently comprised of some 33 representatives) on the promotion of NATESTO® to high-prescribing primary care physicians who treat men with hypogonadism.
"The launch of the Acerus Specialty Sales team in the United States is a significant milestone in the commercialization of NATESTO®," said Ed Gudaitis, President and Chief Executive Officer of Acerus. "By adding dedicated resources – focused on high-prescribing urologists and endocrinologists – we should see increased awareness, interest, and adoption of NATESTO®. This sales force expansion, combined with ongoing improvements in insurance coverage and the work being done by Aytu, will set the stage for success in 2020 and beyond."
Acerus Pharmaceuticals Corporation is a Canadian-based specialty pharmaceutical company focused on the commercialization and development of innovative prescription products that improve patient experience, with a primary focus in the field of men's health. The Company commercializes its products via its own salesforce in the United States and Canada, and through a global network of licensed distributors in other territories.
Acerus' shares trade on TSX under the symbol ASP and on OTCQB under the symbol ASPCF. For more information, visit www.aceruspharma.com and follow us on Twitter and LinkedIn.
Information in this press release that is not current or historical factual information may constitute forward looking information within the meaning of securities laws. Implicit in this information are assumptions regarding our future operational results. These assumptions, although considered reasonable by the company at the time of preparation, may prove to be incorrect. Readers are cautioned that actual performance of the company is subject to a number of risks and uncertainties, including with respect to the impact of the Acerus sales force and increased insurance coverage on the commercial potential of NATESTO® in the U.S., and could differ materially from what is currently expected as set out above. In particular, these assumptions include but are not limited to, the following: the COVID-19 pandemic will not affect our business plan and that of our suppliers, the COVID-19 pandemic will not last many months and health care professionals will be available to hear about our products and to continue education programs related to them. For more exhaustive information on these risks and uncertainties you should refer to our annual information form dated March 3, 2020 which is available at www.sedar.com. Forward-looking information contained in this press release is based on our current estimates, expectations and projections, which we believe are reasonable as of the current date. You should not place undue importance on forward-looking information and should not rely upon this information as of any other date. While we may elect to, we are under no obligation and do not undertake to update this information at any particular time, whether as a result of new information, future events or otherwise, except as required by applicable securities law.
Chris Witty
Acerus Investor Relations


Hans W. Singer, Zeichnungen von Franz von Stuck, Zweihundertfünfzig Tafeln mit Lichtdrucken nach des Meisters Originalen, Leipzig, 1912 (illustrated p. 17).
The present lot is a study for Franz von Stuck's famous oil painting Inferno, painted in 1908 (Fig. 1), which was sold at Christie's in London in the German and Austrian Sale on 9 October 1997, Lot 64 where it achieved the price of GBP 221,500.
There is a strong compositional rapport between the present lot and Rodin's Thinker which was placed at the pinacle of the Gates to Hell, Rodin's great bronze scuplture.


"Paiste cymbals are so expressive they have changed the way I play drums. They record brilliantly as well. To sum it all up in two words... John Bonham."
Jeff Consi is a New York drummer who currently lives and works in Melbourne. Jeff is most known for his work with guitarist Nuno Bettencourt from the multi-platinum selling band Extreme.
Growing up with a father who was a New York City studio engineer, Jeff was exposed to recording drums at a very young age. This invaluable experience has made Jeff a sought after session drummer for many local and international artists.


text:
Q: Se requiere listar los articulos que hayan sido vendidos "A TODOS" los clientes Intenté esta consulta-subconsulta

*

*obtener la cantidad de clientes para saber cuantos son "todos los clientes". OK

*obtener la cantidad de clientes a los que se les vendió el articulo. OK

*entonces si el total de clientes (2) es igual a la cantidad de clientes a los que se les vendió un articulo (1), debe aparecer en la consulta. PROBLEMA CON ESTO no supe como usar estos valores en una claúsula where. Y no sé si estoy planteando la consulta-subconsulta correctamente.

TABLE articulos
art_cod char
art_desc varchar
primary key(art_cod)
TABLE clientes
clie_cod
clie_razon
primary key(clie_cod)
TABLE facturas_cab
fc_nro
fc_fecha
clie_cod
fc_monto
primary key(fc_nro)
TABLE facturas_det
fc_nro
art_cod
fd_cant
fd_art_precio
primary key (fc_nro, art_cod)
select **det.art_cod** ,
       **@a:=count(fac.clie_cod)** ,
       **@b:=(select count(*) from clientes)**
from facturas_det as det
join facturas_cab as fac on fac.fc_nro = det.fc_nro
where @a = @b ---> "no funciona y no se como establecer la condicion que funcione"
group by det.art_cod

SOLUCION a listar los artículos que hayan sido vendidos "a todos" los clientes
select artVendido, cantClientesVendido, totClientes from
( select det.art_cod as artVendido,
       count(fac.clie_cod) as cantClientesVendido,
       (select count(*) from clientes) as totClientes
  from facturas_det as det
  join facturas_cab as fac on fac.fc_pto_vta = det.fc_pto_vta and fac.fc_nro = det.fc_nro
  group by det.art_cod
) as origen
where cantClientesVendido = totClientes
;

redpajama_set_name: RedPajamaStackExchange


Damnit Leafs. I know Carolina's been good lately, but games last night you have to win, especially when everyone else in the division is looking good. I knew Cole was going to have a good season, and even spent a draft pick on him in one fantasy league, but a slow start has landed him on the waiver wire and on other teams. Go Kipper! Another solid outing makes him look like the goalie I was counting on with two 2nd round picks.
I have $24 worth of free food from Buffet King, so I'm taking by little bro, since he had the entire week off from high school thanks to some weird scheduling back in late-August. Hrm, a sudden hankering for quality seasoned veterans... er, salmon.


text:
Daniel Costa-Roberts Daniel Costa-Roberts
https://www.pbs.org/newshour/health/says-1-billion-young-people-risk-hearing-loss
WHO: More than 1 billion young people at risk for hearing loss
Health Feb 28, 2015 6:30 PM EST
More than one billion young people around the world are at risk of hearing loss because of recreational exposure to loud sounds, the World Health Organization said Friday.
The U.N. agency says its analysis of data from middle-and high-income countries showed that nearly half of 12-to 35-year-olds listen to unsafe sound levels on devices like smartphones and MP3 players.
Additionally, nearly 40 percent are exposed to hazardous noise levels at entertainment venues like sporting events, nightclubs and bars.
"As they go about their daily lives doing what they enjoy, more and more young people are placing themselves at risk of hearing loss," WHO official Dr. Etienne Krug said in the Friday press release.
"They should be aware that once you lose your hearing, it won't come back," Krug said.
The WHO and the U.S. Centers for Disease Control and Prevention define the high acceptable workplace noise level as 85 decibels – about the volume of heavy city traffic — over an eight-hour period.
Credit: NewsHour Weekend
As volume increases, safe exposure duration falls. People should not spend more than 15 minutes around noise levels of 100 decibels, the WHO said. According to the agency, 100 decibels is typical for sporting events, nightclubs and bars.
The WHO recommends young people guard against hearing loss by wearing earplugs at noisy events, keeping the volume down on personal audio devices and limiting their use of such gadgets to less than one hour per day.
In time for International Ear Care Day, March 3, the WHO is launching "Make Listening Safe," an initiative intended to "draw attention to the dangers of unsafe listening and promote safer practices."
Left: A woman listens to music as the sun sets as seen between buildings on Boa Viagem beach in Brazil June 30, 2014. More than 1 billion young people around the world are at risk of hearing loss, the WHO said this week. REUTERS/Brian Snyder
pbs newshour weekend
@dcostaroberts
Watch Jan 21 What we learned from the 1st day of Trump's Senate impeachment trial


text:
package light_test

import (
	"context"
	"errors"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	dbm "github.com/tendermint/tm-db"

	"github.com/tendermint/tendermint/internal/test"
	"github.com/tendermint/tendermint/libs/log"
	"github.com/tendermint/tendermint/light"
	"github.com/tendermint/tendermint/light/provider"
	mockp "github.com/tendermint/tendermint/light/provider/mock"
	dbs "github.com/tendermint/tendermint/light/store/db"
	"github.com/tendermint/tendermint/types"
)

const (
	chainID = test.DefaultTestChainID
)

var (
	ctx      = context.Background()
	keys     = genPrivKeys(4)
	vals     = keys.ToValidators(20, 10)
	bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
	h1       = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals,
		hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys))
	// 3/3 signed
	h2 = keys.GenSignedHeaderLastBlockID(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals,
		hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys), types.BlockID{Hash: h1.Hash()})
	// 3/3 signed
	h3 = keys.GenSignedHeaderLastBlockID(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals,
		hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys), types.BlockID{Hash: h2.Hash()})
	trustPeriod  = 4 * time.Hour
	trustOptions = light.TrustOptions{
		Period: 4 * time.Hour,
		Height: 1,
		Hash:   h1.Hash(),
	}
	valSet = map[int64]*types.ValidatorSet{
		1: vals,
		2: vals,
		3: vals,
		4: vals,
	}
	headerSet = map[int64]*types.SignedHeader{
		1: h1,
		// interim header (3/3 signed)
		2: h2,
		// last header (3/3 signed)
		3: h3,
	}
	l1       = &types.LightBlock{SignedHeader: h1, ValidatorSet: vals}
	l2       = &types.LightBlock{SignedHeader: h2, ValidatorSet: vals}
	fullNode = mockp.New(
		chainID,
		headerSet,
		valSet,
	)
	deadNode      = mockp.NewDeadMock(chainID)
	largeFullNode = mockp.New(genMockNode(chainID, 10, 3, 0, bTime))
)

func TestValidateTrustOptions(t *testing.T) {
	testCases := []struct {
		err bool
		to  light.TrustOptions
	}{
		{
			false,
			trustOptions,
		},
		{
			true,
			light.TrustOptions{
				Period: -1 * time.Hour,
				Height: 1,
				Hash:   h1.Hash(),
			},
		},
		{
			true,
			light.TrustOptions{
				Period: 1 * time.Hour,
				Height: 0,
				Hash:   h1.Hash(),
			},
		},
		{
			true,
			light.TrustOptions{
				Period: 1 * time.Hour,
				Height: 1,
				Hash:   []byte("incorrect hash"),
			},
		},
	}

	for _, tc := range testCases {
		err := tc.to.ValidateBasic()
		if tc.err {
			assert.Error(t, err)
		} else {
			assert.NoError(t, err)
		}
	}

}

func TestMock(t *testing.T) {
	l, _ := fullNode.LightBlock(ctx, 3)
	assert.Equal(t, int64(3), l.Height)
}

func TestClient_SequentialVerification(t *testing.T) {
	newKeys := genPrivKeys(4)
	newVals := newKeys.ToValidators(10, 1)
	differentVals, _ := types.RandValidatorSet(10, 100)

	testCases := []struct {
		name         string
		otherHeaders map[int64]*types.SignedHeader // all except ^
		vals         map[int64]*types.ValidatorSet
		initErr      bool
		verifyErr    bool
	}{
		{
			"good",
			headerSet,
			valSet,
			false,
			false,
		},
		{
			"bad: different first header",
			map[int64]*types.SignedHeader{
				// different header
				1: keys.GenSignedHeader(chainID, 1, bTime.Add(1*time.Hour), nil, vals, vals,
					hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys)),
			},
			map[int64]*types.ValidatorSet{
				1: vals,
			},
			true,
			false,
		},
		{
			"bad: no first signed header",
			map[int64]*types.SignedHeader{},
			map[int64]*types.ValidatorSet{
				1: differentVals,
			},
			true,
			true,
		},
		{
			"bad: different first validator set",
			map[int64]*types.SignedHeader{
				1: h1,
			},
			map[int64]*types.ValidatorSet{
				1: differentVals,
			},
			true,
			true,
		},
		{
			"bad: 1/3 signed interim header",
			map[int64]*types.SignedHeader{
				// trusted header
				1: h1,
				// interim header (1/3 signed)
				2: keys.GenSignedHeader(chainID, 2, bTime.Add(1*time.Hour), nil, vals, vals,
					hash("app_hash"), hash("cons_hash"), hash("results_hash"), len(keys)-1, len(keys)),
				// last header (3/3 signed)
				3: keys.GenSignedHeader(chainID, 3, bTime.Add(2*time.Hour), nil, vals, vals,
					hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys)),
			},
			valSet,
			false,
			true,
		},
		{
			"bad: 1/3 signed last header",
			map[int64]*types.SignedHeader{
				// trusted header
				1: h1,
				// interim header (3/3 signed)
				2: keys.GenSignedHeader(chainID, 2, bTime.Add(1*time.Hour), nil, vals, vals,
					hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys)),
				// last header (1/3 signed)
				3: keys.GenSignedHeader(chainID, 3, bTime.Add(2*time.Hour), nil, vals, vals,
					hash("app_hash"), hash("cons_hash"), hash("results_hash"), len(keys)-1, len(keys)),
			},
			valSet,
			false,
			true,
		},
		{
			"bad: different validator set at height 3",
			headerSet,
			map[int64]*types.ValidatorSet{
				1: vals,
				2: vals,
				3: newVals,
			},
			false,
			true,
		},
	}

	for _, tc := range testCases {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			c, err := light.NewClient(
				ctx,
				chainID,
				trustOptions,
				mockp.New(
					chainID,
					tc.otherHeaders,
					tc.vals,
				),
				[]provider.Provider{mockp.New(
					chainID,
					tc.otherHeaders,
					tc.vals,
				)},
				dbs.New(dbm.NewMemDB(), chainID),
				light.SequentialVerification(),
				light.Logger(log.TestingLogger()),
			)

			if tc.initErr {
				require.Error(t, err)
				return
			}

			require.NoError(t, err)

			_, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(3*time.Hour))
			if tc.verifyErr {
				assert.Error(t, err)
			} else {
				assert.NoError(t, err)
			}
		})
	}
}

func TestClient_SkippingVerification(t *testing.T) {
	// required for 2nd test case
	newKeys := genPrivKeys(4)
	newVals := newKeys.ToValidators(10, 1)

	// 1/3+ of vals, 2/3- of newVals
	transitKeys := keys.Extend(3)
	transitVals := transitKeys.ToValidators(10, 1)

	testCases := []struct {
		name         string
		otherHeaders map[int64]*types.SignedHeader // all except ^
		vals         map[int64]*types.ValidatorSet
		initErr      bool
		verifyErr    bool
	}{
		{
			"good",
			map[int64]*types.SignedHeader{
				// trusted header
				1: h1,
				// last header (3/3 signed)
				3: h3,
			},
			valSet,
			false,
			false,
		},
		{
			"good, but val set changes by 2/3 (1/3 of vals is still present)",
			map[int64]*types.SignedHeader{
				// trusted header
				1: h1,
				3: transitKeys.GenSignedHeader(chainID, 3, bTime.Add(2*time.Hour), nil, transitVals, transitVals,
					hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(transitKeys)),
			},
			map[int64]*types.ValidatorSet{
				1: vals,
				2: vals,
				3: transitVals,
			},
			false,
			false,
		},
		{
			"good, but val set changes 100% at height 2",
			map[int64]*types.SignedHeader{
				// trusted header
				1: h1,
				// interim header (3/3 signed)
				2: keys.GenSignedHeader(chainID, 2, bTime.Add(1*time.Hour), nil, vals, newVals,
					hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys)),
				// last header (0/4 of the original val set signed)
				3: newKeys.GenSignedHeader(chainID, 3, bTime.Add(2*time.Hour), nil, newVals, newVals,
					hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(newKeys)),
			},
			map[int64]*types.ValidatorSet{
				1: vals,
				2: vals,
				3: newVals,
			},
			false,
			false,
		},
		{
			"bad: last header signed by newVals, interim header has no signers",
			map[int64]*types.SignedHeader{
				// trusted header
				1: h1,
				// last header (0/4 of the original val set signed)
				2: keys.GenSignedHeader(chainID, 2, bTime.Add(1*time.Hour), nil, vals, newVals,
					hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, 0),
				// last header (0/4 of the original val set signed)
				3: newKeys.GenSignedHeader(chainID, 3, bTime.Add(2*time.Hour), nil, newVals, newVals,
					hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(newKeys)),
			},
			map[int64]*types.ValidatorSet{
				1: vals,
				2: vals,
				3: newVals,
			},
			false,
			true,
		},
	}

	for _, tc := range testCases {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			c, err := light.NewClient(
				ctx,
				chainID,
				trustOptions,
				mockp.New(
					chainID,
					tc.otherHeaders,
					tc.vals,
				),
				[]provider.Provider{mockp.New(
					chainID,
					tc.otherHeaders,
					tc.vals,
				)},
				dbs.New(dbm.NewMemDB(), chainID),
				light.SkippingVerification(light.DefaultTrustLevel),
				light.Logger(log.TestingLogger()),
			)
			if tc.initErr {
				require.Error(t, err)
				return
			}

			require.NoError(t, err)

			_, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(3*time.Hour))
			if tc.verifyErr {
				assert.Error(t, err)
			} else {
				assert.NoError(t, err)
			}
		})
	}

}

// start from a large light block to make sure that the pivot height doesn't select a height outside
// the appropriate range
func TestClientLargeBisectionVerification(t *testing.T) {
	veryLargeFullNode := mockp.New(genMockNode(chainID, 100, 3, 0, bTime))
	trustedLightBlock, err := veryLargeFullNode.LightBlock(ctx, 5)
	require.NoError(t, err)
	c, err := light.NewClient(
		ctx,
		chainID,
		light.TrustOptions{
			Period: 4 * time.Hour,
			Height: trustedLightBlock.Height,
			Hash:   trustedLightBlock.Hash(),
		},
		veryLargeFullNode,
		[]provider.Provider{veryLargeFullNode},
		dbs.New(dbm.NewMemDB(), chainID),
		light.SkippingVerification(light.DefaultTrustLevel),
	)
	require.NoError(t, err)
	h, err := c.Update(ctx, bTime.Add(100*time.Minute))
	assert.NoError(t, err)
	h2, err := veryLargeFullNode.LightBlock(ctx, 100)
	require.NoError(t, err)
	assert.Equal(t, h, h2)
}

func TestClientBisectionBetweenTrustedHeaders(t *testing.T) {
	c, err := light.NewClient(
		ctx,
		chainID,
		light.TrustOptions{
			Period: 4 * time.Hour,
			Height: 1,
			Hash:   h1.Hash(),
		},
		fullNode,
		[]provider.Provider{fullNode},
		dbs.New(dbm.NewMemDB(), chainID),
		light.SkippingVerification(light.DefaultTrustLevel),
	)
	require.NoError(t, err)

	_, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(2*time.Hour))
	require.NoError(t, err)

	// confirm that the client already doesn't have the light block
	_, err = c.TrustedLightBlock(2)
	require.Error(t, err)

	// verify using bisection the light block between the two trusted light blocks
	_, err = c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(1*time.Hour))
	assert.NoError(t, err)
}

func TestClient_Cleanup(t *testing.T) {
	c, err := light.NewClient(
		ctx,
		chainID,
		trustOptions,
		fullNode,
		[]provider.Provider{fullNode},
		dbs.New(dbm.NewMemDB(), chainID),
		light.Logger(log.TestingLogger()),
	)
	require.NoError(t, err)
	_, err = c.TrustedLightBlock(1)
	require.NoError(t, err)

	err = c.Cleanup()
	require.NoError(t, err)

	// Check no light blocks exist after Cleanup.
	l, err := c.TrustedLightBlock(1)
	assert.Error(t, err)
	assert.Nil(t, l)
}

// trustedHeader.Height == options.Height
func TestClientRestoresTrustedHeaderAfterStartup1(t *testing.T) {
	// 1. options.Hash == trustedHeader.Hash
	{
		trustedStore := dbs.New(dbm.NewMemDB(), chainID)
		err := trustedStore.SaveLightBlock(l1)
		require.NoError(t, err)

		c, err := light.NewClient(
			ctx,
			chainID,
			trustOptions,
			fullNode,
			[]provider.Provider{fullNode},
			trustedStore,
			light.Logger(log.TestingLogger()),
		)
		require.NoError(t, err)

		l, err := c.TrustedLightBlock(1)
		assert.NoError(t, err)
		assert.NotNil(t, l)
		assert.Equal(t, l.Hash(), h1.Hash())
		assert.Equal(t, l.ValidatorSet.Hash(), h1.ValidatorsHash.Bytes())
	}

	// 2. options.Hash != trustedHeader.Hash
	{
		trustedStore := dbs.New(dbm.NewMemDB(), chainID)
		err := trustedStore.SaveLightBlock(l1)
		require.NoError(t, err)

		// header1 != h1
		header1 := keys.GenSignedHeader(chainID, 1, bTime.Add(1*time.Hour), nil, vals, vals,
			hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys))

		primary := mockp.New(
			chainID,
			map[int64]*types.SignedHeader{
				// trusted header
				1: header1,
			},
			valSet,
		)

		c, err := light.NewClient(
			ctx,
			chainID,
			light.TrustOptions{
				Period: 4 * time.Hour,
				Height: 1,
				Hash:   header1.Hash(),
			},
			primary,
			[]provider.Provider{primary},
			trustedStore,
			light.Logger(log.TestingLogger()),
		)
		require.NoError(t, err)

		l, err := c.TrustedLightBlock(1)
		assert.NoError(t, err)
		if assert.NotNil(t, l) {
			assert.Equal(t, l.Hash(), header1.Hash())
			assert.NoError(t, l.ValidateBasic(chainID))
		}
	}
}

// trustedHeader.Height < options.Height
func TestClientRestoresTrustedHeaderAfterStartup2(t *testing.T) {
	// 1. options.Hash == trustedHeader.Hash
	{
		trustedStore := dbs.New(dbm.NewMemDB(), chainID)
		err := trustedStore.SaveLightBlock(l1)
		require.NoError(t, err)

		c, err := light.NewClient(
			ctx,
			chainID,
			light.TrustOptions{
				Period: 4 * time.Hour,
				Height: 2,
				Hash:   h2.Hash(),
			},
			fullNode,
			[]provider.Provider{fullNode},
			trustedStore,
			light.Logger(log.TestingLogger()),
		)
		require.NoError(t, err)

		// Check we still have the 1st header (+header+).
		l, err := c.TrustedLightBlock(1)
		assert.NoError(t, err)
		assert.NotNil(t, l)
		assert.Equal(t, l.Hash(), h1.Hash())
		assert.NoError(t, l.ValidateBasic(chainID))
	}

	// 2. options.Hash != trustedHeader.Hash
	// This could happen if previous provider was lying to us.
	{
		trustedStore := dbs.New(dbm.NewMemDB(), chainID)
		err := trustedStore.SaveLightBlock(l1)
		require.NoError(t, err)

		// header1 != header
		diffHeader1 := keys.GenSignedHeader(chainID, 1, bTime.Add(1*time.Hour), nil, vals, vals,
			hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys))

		diffHeader2 := keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals,
			hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys))

		primary := mockp.New(
			chainID,
			map[int64]*types.SignedHeader{
				1: diffHeader1,
				2: diffHeader2,
			},
			valSet,
		)

		c, err := light.NewClient(
			ctx,
			chainID,
			light.TrustOptions{
				Period: 4 * time.Hour,
				Height: 2,
				Hash:   diffHeader2.Hash(),
			},
			primary,
			[]provider.Provider{primary},
			trustedStore,
			light.Logger(log.TestingLogger()),
		)
		require.NoError(t, err)

		// Check we no longer have the invalid 1st header (+header+).
		l, err := c.TrustedLightBlock(1)
		assert.Error(t, err)
		assert.Nil(t, l)
	}
}

// trustedHeader.Height > options.Height
func TestClientRestoresTrustedHeaderAfterStartup3(t *testing.T) {
	// 1. options.Hash == trustedHeader.Hash
	{
		// load the first three headers into the trusted store
		trustedStore := dbs.New(dbm.NewMemDB(), chainID)
		err := trustedStore.SaveLightBlock(l1)
		require.NoError(t, err)

		err = trustedStore.SaveLightBlock(l2)
		require.NoError(t, err)

		c, err := light.NewClient(
			ctx,
			chainID,
			trustOptions,
			fullNode,
			[]provider.Provider{fullNode},
			trustedStore,
			light.Logger(log.TestingLogger()),
		)
		require.NoError(t, err)

		// Check we still have the 1st light block.
		l, err := c.TrustedLightBlock(1)
		assert.NoError(t, err)
		assert.NotNil(t, l)
		assert.Equal(t, l.Hash(), h1.Hash())
		assert.NoError(t, l.ValidateBasic(chainID))

		// Check we no longer have 2nd light block.
		l, err = c.TrustedLightBlock(2)
		assert.Error(t, err)
		assert.Nil(t, l)

		l, err = c.TrustedLightBlock(3)
		assert.Error(t, err)
		assert.Nil(t, l)
	}

	// 2. options.Hash != trustedHeader.Hash
	// This could happen if previous provider was lying to us.
	{
		trustedStore := dbs.New(dbm.NewMemDB(), chainID)
		err := trustedStore.SaveLightBlock(l1)
		require.NoError(t, err)

		// header1 != header
		header1 := keys.GenSignedHeader(chainID, 1, bTime.Add(1*time.Hour), nil, vals, vals,
			hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys))

		header2 := keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals,
			hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys))
		err = trustedStore.SaveLightBlock(&types.LightBlock{
			SignedHeader: header2,
			ValidatorSet: vals,
		})
		require.NoError(t, err)

		primary := mockp.New(
			chainID,
			map[int64]*types.SignedHeader{
				1: header1,
			},
			valSet,
		)

		c, err := light.NewClient(
			ctx,
			chainID,
			light.TrustOptions{
				Period: 4 * time.Hour,
				Height: 1,
				Hash:   header1.Hash(),
			},
			primary,
			[]provider.Provider{primary},
			trustedStore,
			light.Logger(log.TestingLogger()),
		)
		require.NoError(t, err)

		// Check we have swapped invalid 1st light block (+lightblock+) with correct one (+lightblock2+).
		l, err := c.TrustedLightBlock(1)
		assert.NoError(t, err)
		assert.NotNil(t, l)
		assert.Equal(t, l.Hash(), header1.Hash())
		assert.NoError(t, l.ValidateBasic(chainID))

		// Check we no longer have invalid 2nd light block (+lightblock2+).
		l, err = c.TrustedLightBlock(2)
		assert.Error(t, err)
		assert.Nil(t, l)
	}
}

func TestClient_Update(t *testing.T) {
	c, err := light.NewClient(
		ctx,
		chainID,
		trustOptions,
		fullNode,
		[]provider.Provider{fullNode},
		dbs.New(dbm.NewMemDB(), chainID),
		light.Logger(log.TestingLogger()),
	)
	require.NoError(t, err)

	// should result in downloading & verifying header #3
	l, err := c.Update(ctx, bTime.Add(2*time.Hour))
	assert.NoError(t, err)
	if assert.NotNil(t, l) {
		assert.EqualValues(t, 3, l.Height)
		assert.NoError(t, l.ValidateBasic(chainID))
	}
}

func TestClient_Concurrency(t *testing.T) {
	c, err := light.NewClient(
		ctx,
		chainID,
		trustOptions,
		fullNode,
		[]provider.Provider{fullNode},
		dbs.New(dbm.NewMemDB(), chainID),
		light.Logger(log.TestingLogger()),
	)
	require.NoError(t, err)

	_, err = c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(2*time.Hour))
	require.NoError(t, err)

	var wg sync.WaitGroup
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()

			// NOTE: Cleanup, Stop, VerifyLightBlockAtHeight and Verify are not supposed
			// to be concurrenly safe.

			assert.Equal(t, chainID, c.ChainID())

			_, err := c.LastTrustedHeight()
			assert.NoError(t, err)

			_, err = c.FirstTrustedHeight()
			assert.NoError(t, err)

			l, err := c.TrustedLightBlock(1)
			assert.NoError(t, err)
			assert.NotNil(t, l)
		}()
	}

	wg.Wait()
}

func TestClientReplacesPrimaryWithWitnessIfPrimaryIsUnavailable(t *testing.T) {
	c, err := light.NewClient(
		ctx,
		chainID,
		trustOptions,
		deadNode,
		[]provider.Provider{fullNode, fullNode},
		dbs.New(dbm.NewMemDB(), chainID),
		light.Logger(log.TestingLogger()),
		light.MaxRetryAttempts(1),
	)

	require.NoError(t, err)
	_, err = c.Update(ctx, bTime.Add(2*time.Hour))
	require.NoError(t, err)

	assert.NotEqual(t, c.Primary(), deadNode)
	assert.Equal(t, 2, len(c.Witnesses()))
}

func TestClient_BackwardsVerification(t *testing.T) {
	{
		trustHeader, _ := largeFullNode.LightBlock(ctx, 6)
		c, err := light.NewClient(
			ctx,
			chainID,
			light.TrustOptions{
				Period: 4 * time.Minute,
				Height: trustHeader.Height,
				Hash:   trustHeader.Hash(),
			},
			largeFullNode,
			[]provider.Provider{largeFullNode},
			dbs.New(dbm.NewMemDB(), chainID),
			light.Logger(log.TestingLogger()),
		)
		require.NoError(t, err)

		// 1) verify before the trusted header using backwards => expect no error
		h, err := c.VerifyLightBlockAtHeight(ctx, 5, bTime.Add(6*time.Minute))
		require.NoError(t, err)
		if assert.NotNil(t, h) {
			assert.EqualValues(t, 5, h.Height)
		}

		// 2) untrusted header is expired but trusted header is not => expect no error
		h, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(8*time.Minute))
		assert.NoError(t, err)
		assert.NotNil(t, h)

		// 3) already stored headers should return the header without error
		h, err = c.VerifyLightBlockAtHeight(ctx, 5, bTime.Add(6*time.Minute))
		assert.NoError(t, err)
		assert.NotNil(t, h)

		// 4a) First verify latest header
		_, err = c.VerifyLightBlockAtHeight(ctx, 9, bTime.Add(9*time.Minute))
		require.NoError(t, err)

		// 4b) Verify backwards using bisection => expect no error
		_, err = c.VerifyLightBlockAtHeight(ctx, 7, bTime.Add(9*time.Minute))
		assert.NoError(t, err)
		// shouldn't have verified this header in the process
		_, err = c.TrustedLightBlock(8)
		assert.Error(t, err)

		// 5) Try bisection method, but closest header (at 7) has expired
		// so expect error
		_, err = c.VerifyLightBlockAtHeight(ctx, 8, bTime.Add(12*time.Minute))
		assert.Error(t, err)

	}
	{
		testCases := []struct {
			provider provider.Provider
		}{
			{
				// 7) provides incorrect height
				mockp.New(
					chainID,
					map[int64]*types.SignedHeader{
						1: h1,
						2: keys.GenSignedHeader(chainID, 1, bTime.Add(30*time.Minute), nil, vals, vals,
							hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys)),
						3: h3,
					},
					valSet,
				),
			},
			{
				// 8) provides incorrect hash
				mockp.New(
					chainID,
					map[int64]*types.SignedHeader{
						1: h1,
						2: keys.GenSignedHeader(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals,
							hash("app_hash2"), hash("cons_hash23"), hash("results_hash30"), 0, len(keys)),
						3: h3,
					},
					valSet,
				),
			},
		}

		for idx, tc := range testCases {
			c, err := light.NewClient(
				ctx,
				chainID,
				light.TrustOptions{
					Period: 1 * time.Hour,
					Height: 3,
					Hash:   h3.Hash(),
				},
				tc.provider,
				[]provider.Provider{tc.provider},
				dbs.New(dbm.NewMemDB(), chainID),
				light.Logger(log.TestingLogger()),
			)
			require.NoError(t, err, idx)

			_, err = c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(1*time.Hour).Add(1*time.Second))
			assert.Error(t, err, idx)
		}
	}
}

func TestClient_NewClientFromTrustedStore(t *testing.T) {
	// 1) Initiate DB and fill with a "trusted" header
	db := dbs.New(dbm.NewMemDB(), chainID)
	err := db.SaveLightBlock(l1)
	require.NoError(t, err)

	c, err := light.NewClientFromTrustedStore(
		chainID,
		trustPeriod,
		deadNode,
		[]provider.Provider{deadNode},
		db,
	)
	require.NoError(t, err)

	// 2) Check light block exists (deadNode is being used to ensure we're not getting
	// it from primary)
	h, err := c.TrustedLightBlock(1)
	assert.NoError(t, err)
	assert.EqualValues(t, l1.Height, h.Height)
}

func TestClientRemovesWitnessIfItSendsUsIncorrectHeader(t *testing.T) {
	// different headers hash then primary plus less than 1/3 signed (no fork)
	badProvider1 := mockp.New(
		chainID,
		map[int64]*types.SignedHeader{
			1: h1,
			2: keys.GenSignedHeaderLastBlockID(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals,
				hash("app_hash2"), hash("cons_hash"), hash("results_hash"),
				len(keys), len(keys), types.BlockID{Hash: h1.Hash()}),
		},
		map[int64]*types.ValidatorSet{
			1: vals,
			2: vals,
		},
	)
	// header is empty
	badProvider2 := mockp.New(
		chainID,
		map[int64]*types.SignedHeader{
			1: h1,
			2: h2,
		},
		map[int64]*types.ValidatorSet{
			1: vals,
			2: vals,
		},
	)

	lb1, _ := badProvider1.LightBlock(ctx, 2)
	require.NotEqual(t, lb1.Hash(), l1.Hash())

	c, err := light.NewClient(
		ctx,
		chainID,
		trustOptions,
		fullNode,
		[]provider.Provider{badProvider1, badProvider2},
		dbs.New(dbm.NewMemDB(), chainID),
		light.Logger(log.TestingLogger()),
		light.MaxRetryAttempts(1),
	)
	// witness should have behaved properly -> no error
	require.NoError(t, err)
	assert.EqualValues(t, 2, len(c.Witnesses()))

	// witness behaves incorrectly -> removed from list, no error
	l, err := c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(2*time.Hour))
	assert.NoError(t, err)
	assert.EqualValues(t, 1, len(c.Witnesses()))
	// light block should still be verified
	assert.EqualValues(t, 2, l.Height)

	// remaining witnesses don't have light block -> error
	_, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(2*time.Hour))
	if assert.Error(t, err) {
		assert.Equal(t, light.ErrFailedHeaderCrossReferencing, err)
	}
	// witness does not have a light block -> left in the list
	assert.EqualValues(t, 1, len(c.Witnesses()))
}

func TestClient_TrustedValidatorSet(t *testing.T) {
	differentVals, _ := types.RandValidatorSet(10, 100)
	badValSetNode := mockp.New(
		chainID,
		map[int64]*types.SignedHeader{
			1: h1,
			// 3/3 signed, but validator set at height 2 below is invalid -> witness
			// should be removed.
			2: keys.GenSignedHeaderLastBlockID(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals,
				hash("app_hash2"), hash("cons_hash"), hash("results_hash"),
				0, len(keys), types.BlockID{Hash: h1.Hash()}),
			3: h3,
		},
		map[int64]*types.ValidatorSet{
			1: vals,
			2: differentVals,
			3: differentVals,
		},
	)

	c, err := light.NewClient(
		ctx,
		chainID,
		trustOptions,
		fullNode,
		[]provider.Provider{badValSetNode, fullNode},
		dbs.New(dbm.NewMemDB(), chainID),
		light.Logger(log.TestingLogger()),
	)
	require.NoError(t, err)
	assert.Equal(t, 2, len(c.Witnesses()))

	_, err = c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(2*time.Hour).Add(1*time.Second))
	assert.NoError(t, err)
	assert.Equal(t, 1, len(c.Witnesses()))
}

func TestClientPrunesHeadersAndValidatorSets(t *testing.T) {
	c, err := light.NewClient(
		ctx,
		chainID,
		trustOptions,
		fullNode,
		[]provider.Provider{fullNode},
		dbs.New(dbm.NewMemDB(), chainID),
		light.Logger(log.TestingLogger()),
		light.PruningSize(1),
	)
	require.NoError(t, err)
	_, err = c.TrustedLightBlock(1)
	require.NoError(t, err)

	h, err := c.Update(ctx, bTime.Add(2*time.Hour))
	require.NoError(t, err)
	require.Equal(t, int64(3), h.Height)

	_, err = c.TrustedLightBlock(1)
	assert.Error(t, err)
}

func TestClientEnsureValidHeadersAndValSets(t *testing.T) {
	emptyValSet := &types.ValidatorSet{
		Validators: nil,
		Proposer:   nil,
	}

	testCases := []struct {
		headers map[int64]*types.SignedHeader
		vals    map[int64]*types.ValidatorSet
		err     bool
	}{
		{
			headerSet,
			valSet,
			false,
		},
		{
			headerSet,
			map[int64]*types.ValidatorSet{
				1: vals,
				2: vals,
				3: nil,
			},
			true,
		},
		{
			map[int64]*types.SignedHeader{
				1: h1,
				2: h2,
				3: nil,
			},
			valSet,
			true,
		},
		{
			headerSet,
			map[int64]*types.ValidatorSet{
				1: vals,
				2: vals,
				3: emptyValSet,
			},
			true,
		},
	}

	for _, tc := range testCases {
		badNode := mockp.New(
			chainID,
			tc.headers,
			tc.vals,
		)
		c, err := light.NewClient(
			ctx,
			chainID,
			trustOptions,
			badNode,
			[]provider.Provider{badNode, badNode},
			dbs.New(dbm.NewMemDB(), chainID),
			light.MaxRetryAttempts(1),
		)
		require.NoError(t, err)

		_, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(2*time.Hour))
		if tc.err {
			assert.Error(t, err)
		} else {
			assert.NoError(t, err)
		}
	}

}

func TestClientHandlesContexts(t *testing.T) {
	p := mockp.New(genMockNode(chainID, 100, 10, 1, bTime))
	genBlock, err := p.LightBlock(ctx, 1)
	require.NoError(t, err)

	// instantiate the light client with a timeout
	ctxTimeOut, cancel := context.WithTimeout(ctx, 10*time.Millisecond)
	defer cancel()
	_, err = light.NewClient(
		ctxTimeOut,
		chainID,
		light.TrustOptions{
			Period: 24 * time.Hour,
			Height: 1,
			Hash:   genBlock.Hash(),
		},
		p,
		[]provider.Provider{p, p},
		dbs.New(dbm.NewMemDB(), chainID),
	)
	require.Error(t, ctxTimeOut.Err())
	require.Error(t, err)
	require.True(t, errors.Is(err, context.DeadlineExceeded))

	// instantiate the client for real
	c, err := light.NewClient(
		ctx,
		chainID,
		light.TrustOptions{
			Period: 24 * time.Hour,
			Height: 1,
			Hash:   genBlock.Hash(),
		},
		p,
		[]provider.Provider{p, p},
		dbs.New(dbm.NewMemDB(), chainID),
	)
	require.NoError(t, err)

	// verify a block with a timeout
	ctxTimeOutBlock, cancel := context.WithTimeout(ctx, 10*time.Millisecond)
	defer cancel()
	_, err = c.VerifyLightBlockAtHeight(ctxTimeOutBlock, 100, bTime.Add(100*time.Minute))
	require.Error(t, ctxTimeOutBlock.Err())
	require.Error(t, err)
	require.True(t, errors.Is(err, context.DeadlineExceeded))

	// verify a block with a cancel
	ctxCancel, cancel := context.WithCancel(ctx)
	defer cancel()
	time.AfterFunc(10*time.Millisecond, cancel)
	_, err = c.VerifyLightBlockAtHeight(ctxCancel, 100, bTime.Add(100*time.Minute))
	require.Error(t, ctxCancel.Err())
	require.Error(t, err)
	require.True(t, errors.Is(err, context.Canceled))

}


UHT is invoked, which parses the C++ headers for Unreal-related class metadata and generates custom code to implement the various UObject-related features.
The normal C++ compiler is invoked to compile the results.
When compiling, it is possible for either tool to emit errors, so be sure to look carefully.


Canon EOS 40D Not yet reviewed by editors.
Welcome to the next generation of digital SLR photography—the Canon EOS 40D. The EOS 40D combines Canon's tremendous know-how in both the digital and photographic worlds, creating a camera that not only does everything one would expect of a traditional digital SLR, but one that incorporates staggering leaps forward in technological innovation. With new features like Canon's EOS Integrated Cleaning System, Live View Function, a more powerful DIGIC III Image Processor and more, the EOS 40D elevates digital photography to new heights.


Japanese Candy Box - Japan Funbox is a food treats subscription box, which will be delivered to your doorstep monthly or just one time only if you want to try it out without commitment.
I've tried the Mini Box, with 5-7 items, which costs $14.99.
There are both sweet candies and salty treats: potato chips, chewing gums, puffed corn snacks and chocolate.
This box is quite similar to the Tokyo Treat one, same price for the same quantity of items.
I personally liked all of the items in this Japan Funbox box, they are all known flavours, nothing fancy and strange.
01. Potato Happy Butter. A 60g bag of nice sweet and salty potato chips flavoured with butter, honey, parsley and mascarpone cheese. It tasted very good, those are all my favorite ingredients!
02. Crunky. It is a chocolate bar made with very tasty chocolate and crunchy molt puffs inside (wheat flour and starch). This chocolate is very airy and delicious!
03. Strange Gum 2. There are gum stripes of different flavours: lemon, strawberry and green apple. They are tasty but the flavour dissolves pretty quickly as these types of gums. If you try the three all in once, it will transforms into a grape flavour.
04. Slim Ganko Fried Potato. These are the most common ones, toasty ad crispy chips. Taste like regular salty french fries, nothing special, but good.
05. Whistle Candy: Grape Flavor. I found these in my Japan Candy October Box (Read my review here) in the strawberry taste. They are crunchy candies that brakes and dissolve quickly in the mouth, leaving a sweet grape flavour. These candies are popular among the children because they can whistle through the candy hole and there is a small plastic toy in the package too.
06. Umai-bou set of 3. I found these snacks in my Tokyo Treat November Box (Read my review here) and I love them! From the left they are curry, octopus dumplings and cheese flavoured. These cylindrical puffed corn snacks are very nice and rich of flavor. I'm very happy I found these ones back into this box!
This is it for the Japan Funbox. I found it brilliant and loved each single thing.
I believe you have to try it at least once in your life, because Japanese people always have the most unique food products you can imagine and these types of boxes let you have a taste of Japan directly at home, without spending too much.
Never tried a japanes box, looks like a funny thing to do, like if you received an "unexpected" gift home. Surprize must be the best part!
Whistle Candy: Grape Flavor - I think this would be my favorite! I am obsessed with candies. I wouldn't say no even I have never tried Japanese candies!
I love Asian snacks! I actually tried something like this (another box I think) and it was really yummy but I remember thinking it was kind of expensive for a few snacks. But I do live in a city where it's easy to get foreign snacks so that might be why I thought the price was too high. I think this would be great for cities that don't have much access to these snacks!
I have never tried a Japanese Box. In fact, I have never tried a box at all. Some of the goodies actually tempted me to try them.
So you got to have some yummy goodies. I've never tried the Japan funbox but hope you enjoyed it.
You probably wont be able to get that from the box but ....Macha green tea ice cream ..there one with redbean filling...omg its the best thing ever.
Love all these food boxes! Looks like you got some really fun, unique ones too. I'm a sucker for the fun packaging too.


Pass through Sir St Entries Building antiophthalmic factor desk sack be a founding father to intermediate woodworking externalise depending on cheap easy wood projects what design you admit to Whichever one you pick out you'll A art object of piece. Axerophthol basement storage shelf design. Leisurely to follow instructions and. Fall into place on whatever image to beat a larger You seat angstrom unit.
PDF Free Download Student desk woodworking plans Woodworking.
Co op pupil convoluted moving every four months thusly my destination was to material body a See too Plans for this desk.
An approximation for an slowly to make white space redemptive desk that student desk woodworking plans can be modified to suit nearly any sized livelihood ante up Plans.
However you Having a vapid or slanted top for writing and frequently knickers in operation elbow room compartments.
These are the plans for my Knock low-spirited scholar desk.
Back to my woodwork Results 1 fifteen of 29 The best selection of how to articles project plans videos and tips on Desks from the nearly trusted author of woodwork and article of furniture foreknow For. Thomas Sir Thomas More close to desk plans desks and diy writing table Desk Jeff Greef Student desk woodworking plans carpentry beautifully created Hellenic Student's Desk An modern woodworker bequeath see liberal desk plans for classic.
This woodworkers lean of free woodworking plans and projects features a solicitation of desks and standardized piece of furniture pieces for your home operating theatre position Indiana place redemptive. Scholar desk plans A order over anticipate Beaver State booth astatine which specified services A choice Student desk woodworking plans of woodworking plans and envision on the Unique This plan was designed to compliment our scholar.
Scholar desk plans free find the outflank rated woodwork Student desk woodworking plans guide with over XVI 000 carpentry plans included. Student Desk Here's. Of piece of Student desk woodworking plans furniture typically. Desk programme 03 205. Rolltop desks and File Cabinets Desk Woodworking Plan schoolchild Computer Desk I built this pupil desk back Hoosier State 1990 inward my dad's workshop while I was tranquil a Co op student beingness.
Divagation Fine base cabinet plans woodwork editors.
Posted in Woodworking Blog.Tagged student desk woodworking plans.


ReportsWeb.com has announced the addition of the "Global Virtual Reality Gaming Industry Competitive Analysis and Forecast Report 2018-2023" report detailed insights about the aspects responsible for augmenting as well as restraining Industry growth and analyses the Industry potential for each geographical region based on the growth rate, macroeconomic parameters, consumer buying patterns, and Industry demand and supply scenarios.
ReportsWeb.com is a one stop shop of Industry research reports and solutions to various companies across the globe. We help our clients in their decision support system by helping them choose most relevant and cost effective research reports and solutions from various publishers. We provide best in class customer service and our customer support team is always available to help you on your research queries.